From python-checkins at python.org Sun Apr 1 00:34:09 2012 From: python-checkins at python.org (sandro.tosi) Date: Sun, 01 Apr 2012 00:34:09 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_Issue_=2314316=3A_fix_brok?= =?utf8?q?en_link=3B_fix_by_=C3=89ric_Araujo?= Message-ID: http://hg.python.org/devguide/rev/b038bfc67e3d changeset: 498:b038bfc67e3d user: Sandro Tosi date: Sun Apr 01 00:31:55 2012 +0200 summary: Issue #14316: fix broken link; fix by ?ric Araujo files: grammar.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/grammar.rst b/grammar.rst --- a/grammar.rst +++ b/grammar.rst @@ -20,7 +20,7 @@ --------- People are getting this wrong all the time; it took well over a -year before someone `noticed `_ +year before someone `noticed `_ that adding the floor division operator (//) broke the parser module. -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Apr 1 01:08:01 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 01 Apr 2012 01:08:01 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzODcy?= =?utf8?q?=3A_socket=2Edetach=28=29_now_marks_the_socket_closed_=28as_mirr?= =?utf8?q?ored_in_the?= Message-ID: http://hg.python.org/cpython/rev/3a220feafa15 changeset: 76033:3a220feafa15 branch: 3.2 parent: 76030:f96b603278cc user: Antoine Pitrou date: Sun Apr 01 01:00:17 2012 +0200 summary: Issue #13872: socket.detach() now marks the socket closed (as mirrored in the socket repr()). Patch by Matt Joiner. files: Lib/socket.py | 11 +++++++++++ Lib/test/test_socket.py | 1 + Misc/NEWS | 3 +++ 3 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -197,6 +197,17 @@ if self._io_refs <= 0: self._real_close() + def detach(self): + """detach() -> file descriptor + + Close the socket object without closing the underlying file descriptor. + The object cannot be used after this call, but the file descriptor + can be reused for other purposes. The file descriptor is returned. + """ + self._closed = True + return super().detach() + + def fromfd(fd, family, type, proto=0): """ fromfd(fd, family, type[, proto]) -> socket object 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 @@ -951,6 +951,7 @@ f = self.cli_conn.detach() self.assertEqual(f, fileno) # cli_conn cannot be used anymore... + self.assertTrue(self.cli_conn._closed) self.assertRaises(socket.error, self.cli_conn.recv, 1024) self.cli_conn.close() # ...but we can create another socket using the (still open) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -31,6 +31,9 @@ Library ------- +- Issue #13872: socket.detach() now marks the socket closed (as mirrored + in the socket repr()). Patch by Matt Joiner. + - Issue #14406: Fix a race condition when using ``concurrent.futures.wait( return_when=ALL_COMPLETED)``. Patch by Matt Joiner. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 01:08:02 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 01 Apr 2012 01:08:02 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2313872=3A_socket=2Edetach=28=29_now_marks_the_socket?= =?utf8?q?_closed_=28as_mirrored_in_the?= Message-ID: http://hg.python.org/cpython/rev/d2f0c3eb1eed changeset: 76034:d2f0c3eb1eed parent: 76031:9a5ae3f37d06 parent: 76033:3a220feafa15 user: Antoine Pitrou date: Sun Apr 01 01:00:55 2012 +0200 summary: Issue #13872: socket.detach() now marks the socket closed (as mirrored in the socket repr()). Patch by Matt Joiner. files: Lib/socket.py | 11 +++++++++++ Lib/test/test_socket.py | 1 + Misc/NEWS | 3 +++ 3 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -199,6 +199,17 @@ if self._io_refs <= 0: self._real_close() + def detach(self): + """detach() -> file descriptor + + Close the socket object without closing the underlying file descriptor. + The object cannot be used after this call, but the file descriptor + can be reused for other purposes. The file descriptor is returned. + """ + self._closed = True + return super().detach() + + def fromfd(fd, family, type, proto=0): """ fromfd(fd, family, type[, proto]) -> socket object 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 @@ -1574,6 +1574,7 @@ f = self.cli_conn.detach() self.assertEqual(f, fileno) # cli_conn cannot be used anymore... + self.assertTrue(self.cli_conn._closed) self.assertRaises(socket.error, self.cli_conn.recv, 1024) self.cli_conn.close() # ...but we can create another socket using the (still open) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -37,6 +37,9 @@ Library ------- +- Issue #13872: socket.detach() now marks the socket closed (as mirrored + in the socket repr()). Patch by Matt Joiner. + - Issue #14406: Fix a race condition when using ``concurrent.futures.wait( return_when=ALL_COMPLETED)``. Patch by Matt Joiner. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 01:25:21 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 01 Apr 2012 01:25:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314300=3A_Under_Win?= =?utf8?q?dows=2C_sockets_created_using_socket=2Edup=28=29_now_allow?= Message-ID: http://hg.python.org/cpython/rev/5be4d8fc9c44 changeset: 76035:5be4d8fc9c44 user: Antoine Pitrou date: Sun Apr 01 01:14:39 2012 +0200 summary: Issue #14300: Under Windows, sockets created using socket.dup() now allow overlapped I/O. Patch by sbt. files: Misc/NEWS | 3 +++ Modules/socketmodule.c | 2 +- 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -37,6 +37,9 @@ Library ------- +- Issue #14300: Under Windows, sockets created using socket.dup() now allow + overlapped I/O. Patch by sbt. + - Issue #13872: socket.detach() now marks the socket closed (as mirrored in the socket repr()). Patch by Matt Joiner. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -381,7 +381,7 @@ return INVALID_SOCKET; return WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, &info, 0, 0); + FROM_PROTOCOL_INFO, &info, 0, WSA_FLAG_OVERLAPPED); } #define SOCKETCLOSE closesocket #else -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 01:52:28 2012 From: python-checkins at python.org (sandro.tosi) Date: Sun, 01 Apr 2012 01:52:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_fix_typo=3B_tha?= =?utf8?q?nks_to_Robert_Bardos_from_docs=40?= Message-ID: http://hg.python.org/cpython/rev/3623c3e6c049 changeset: 76036:3623c3e6c049 branch: 2.7 parent: 76032:6f8dd543d80a user: Sandro Tosi date: Sun Apr 01 01:49:46 2012 +0200 summary: fix typo; thanks to Robert Bardos from docs@ files: Doc/glossary.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -406,7 +406,7 @@ :meth:`str.lower` method can serve as a key function for case insensitive sorts. Alternatively, an ad-hoc key function can be built from a :keyword:`lambda` expression such as ``lambda r: (r[0], r[2])``. Also, - the :mod:`operator` module provides three key function constuctors: + the :mod:`operator` module provides three key function constructors: :func:`~operator.attrgetter`, :func:`~operator.itemgetter`, and :func:`~operator.methodcaller`. See the :ref:`Sorting HOW TO ` for examples of how to create and use key functions. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 01:52:29 2012 From: python-checkins at python.org (sandro.tosi) Date: Sun, 01 Apr 2012 01:52:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_fix_typo=3B_tha?= =?utf8?q?nks_to_Robert_Bardos_from_docs=40?= Message-ID: http://hg.python.org/cpython/rev/0a4a6f98bd8e changeset: 76037:0a4a6f98bd8e branch: 3.2 parent: 76033:3a220feafa15 user: Sandro Tosi date: Sun Apr 01 01:50:00 2012 +0200 summary: fix typo; thanks to Robert Bardos from docs@ files: Doc/glossary.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -385,7 +385,7 @@ :meth:`str.lower` method can serve as a key function for case insensitive sorts. Alternatively, an ad-hoc key function can be built from a :keyword:`lambda` expression such as ``lambda r: (r[0], r[2])``. Also, - the :mod:`operator` module provides three key function constuctors: + the :mod:`operator` module provides three key function constructors: :func:`~operator.attrgetter`, :func:`~operator.itemgetter`, and :func:`~operator.methodcaller`. See the :ref:`Sorting HOW TO ` for examples of how to create and use key functions. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 01:52:30 2012 From: python-checkins at python.org (sandro.tosi) Date: Sun, 01 Apr 2012 01:52:30 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/51b5f2b90df2 changeset: 76038:51b5f2b90df2 parent: 76035:5be4d8fc9c44 parent: 76037:0a4a6f98bd8e user: Sandro Tosi date: Sun Apr 01 01:50:22 2012 +0200 summary: merge with 3.2 files: Doc/glossary.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -385,7 +385,7 @@ :meth:`str.lower` method can serve as a key function for case insensitive sorts. Alternatively, an ad-hoc key function can be built from a :keyword:`lambda` expression such as ``lambda r: (r[0], r[2])``. Also, - the :mod:`operator` module provides three key function constuctors: + the :mod:`operator` module provides three key function constructors: :func:`~operator.attrgetter`, :func:`~operator.itemgetter`, and :func:`~operator.methodcaller`. See the :ref:`Sorting HOW TO ` for examples of how to create and use key functions. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 04:24:04 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 01 Apr 2012 04:24:04 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_time=2Eget=5Fcl?= =?utf8?q?ock=5Finfo=28=29?= Message-ID: http://hg.python.org/peps/rev/7375d3178b6a changeset: 4183:7375d3178b6a user: Victor Stinner date: Sun Apr 01 04:11:08 2012 +0200 summary: PEP 418: Add time.get_clock_info() files: pep-0418.txt | 23 +++++++++++++++++++++-- 1 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -13,8 +13,8 @@ Abstract ======== -Add time.monotonic(fallback=True) and time.highres() functions to -Python 3.3. +Add time.monotonic(fallback=True), time.highres(), time.get_clock_info(name) +functions to Python 3.3. Rationale @@ -40,6 +40,7 @@ clock is available, falls back to system clock by default, or raises an OSError if *fallback* is False. time.monotonic(fallback=True) cannot go backward. +* time.get_clock_info(name): get information on the specified time function time.time() @@ -208,6 +209,24 @@ highres.use_performance_counter = (os.name == 'nt') highres.use_monotonic = hasattr(time, 'monotonic') +time.get_clock_info(name) +------------------------- + +Get information on the specified time function as a dictionary. Only the following +names are accepted: + + * "clock": time.clock() + * "highres": time.highres() + * "monotonic": time.monotonic() + * "time": time.time() + +The following keys are always present: + + * "function" (str): name of the underlying operating system function (ex: + "QueryPerformanceCounter()" or "clock_gettime(CLOCK_REALTIME)") + * "resolution" (float): resolution in seconds of the function + * "monotonic" (bool): True if the clock is monotonic + Hardware clocks =============== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 1 04:24:05 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 01 Apr 2012 04:24:05 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Drop_fallback_param?= =?utf8?q?eter_of_time=2Emonotonic=28=29?= Message-ID: http://hg.python.org/peps/rev/e6e799e92983 changeset: 4184:e6e799e92983 user: Victor Stinner date: Sun Apr 01 04:23:32 2012 +0200 summary: PEP 418: Drop fallback parameter of time.monotonic() time.monotonic() now always falls back and time.get_clock_info() can be used to check if the clock is monotonic. files: pep-0418.txt | 65 +++++++++++++++++++++------------------ 1 files changed, 35 insertions(+), 30 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -13,8 +13,8 @@ Abstract ======== -Add time.monotonic(fallback=True), time.highres(), time.get_clock_info(name) -functions to Python 3.3. +Add time.monotonic(), time.highres(), time.get_clock_info(name) functions to +Python 3.3. Rationale @@ -25,8 +25,8 @@ * Display the current time to a human (e.g. display a calendar or draw a wall clock): use system clock, i.e. time.time() or datetime.datetime.now(). -* Benchmark, profiling, timeout: time.highres(). -* Event scheduler: time.monotonic(), or time.monotonic(fallback=False). +* Benchmark, profiling: time.highres(). +* Event scheduler, timeout: time.monotonic(). Functions @@ -36,10 +36,8 @@ * time.time(): system clock, "wall clock". * time.highres(): clock with the best accuracy. -* time.monotonic(fallback=True): monotonic clock. If no monotonic - clock is available, falls back to system clock by default, or raises - an OSError if *fallback* is False. time.monotonic(fallback=True) - cannot go backward. +* time.monotonic(): monotonic clock, or system clock if no monotonic + clock is available * time.get_clock_info(name): get information on the specified time function @@ -81,19 +79,16 @@ return _time.time() -time.monotonic(fallback=True) ------------------------------ +time.monotonic() +---------------- -Clock that cannot go backward, its rate is as steady as possible. Its -rate may be adjusted by NTP. The reference point of the returned -value is undefined so only the difference of consecutive calls is -valid. +Monotonic clock, or system clock if the platform does not provide a monotonic +clock (e.g. on GNU/Hurd). Its rate is as steady as possible. Its rate may be +adjusted by NTP. The reference point of the returned value is undefined so +only the difference of consecutive calls is valid. -By default, it falls back to the system clock if no monotonic clock is -available or if the monotonic clock failed, and so it cannot fail. If -fallback is False, it raises OSError if the monotonic clock failed and -NotImplementedError if the platform does not provide a monotonic clock -(e.g. on GNU/Hurd). +Use time.get_clock_info('monotonic')['monotonic'] to check if the clock +monotonic or not. The elapsed time may or may not include time the system spends in sleep or hibernation; this depends on the operating system. @@ -103,10 +98,10 @@ if os.name == 'nt': # GetTickCount64() requires Windows Vista, Server 2008 or later if hasattr(time, '_GetTickCount64'): - def monotonic(fallback=True): + def monotonic(): return _time.GetTickCount64() else: - def monotonic(fallback=True): + def monotonic(): ticks = _time.GetTickCount() if ticks < monotonic.last: # Integer overflow detected @@ -117,7 +112,7 @@ monotonic.delta = 0 elif os.name == 'mac': - def monotonic(fallback=True): + def monotonic(): if monotonic.factor is None: factor = _time.mach_timebase_info() monotonic.factor = timebase[0] / timebase[1] @@ -125,7 +120,7 @@ monotonic.factor = None elif os.name.startswith('sunos'): - def monotonic(fallback=True): + def monotonic(): if monotonic.use_clock_highres: try: time.clock_gettime(time.CLOCK_HIGHRES) @@ -135,8 +130,6 @@ try: return time.gethrtime() except OSError: - if not fallback: - raise monotonic.use_gethrtime = False return time.time() monotonic.use_clock_highres = (hasattr(time, 'clock_gettime') @@ -144,15 +137,13 @@ monotonic.use_gethrtime = True elif hasattr(time, "clock_gettime"): - def monotonic(fallback=True): + def monotonic(): while monotonic.clocks: try: clk_id = monotonic.clocks[0] return time.clock_gettime(clk_id) except OSError: # CLOCK_MONOTONIC_RAW requires a Linux kernel >= 2.6.28 - if len(monotonic.clocks) == 1 and not fallback: - raise del monotonic.clocks[0] return time.time() monotonic.clocks = [] @@ -163,9 +154,7 @@ monotonic.clocks.append(time.CLOCK_MONOTONIC) else: - def monotonic(fallback=True): - if not fallback: - raise NotImplementedError("you platform does not provide any monotonic clock") + def monotonic(): return time.time() On Windows, QueryPerformanceCounter() is not used even though it has a @@ -679,6 +668,21 @@ a monotonic clock with an unspecified starting point +One function with a flag: time.monotonic(fallback=True) +------------------------------------------------------- + + * time.monotonic(fallback=True) falls back to the system clock if no monotonic + clock is available or if the monotonic clock failed. + * time.monotonic(fallback=False) raises OSError if monotonic clock fails and + NotImplementedError if the system does not provide a monotonic clock + +"A keyword argument that gets passed as a constant in the caller is usually +poor API." + +Raising NotImplementedError for a function is something uncommon in Python and +should be avoided. + + One function, no flag --------------------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 1 04:24:04 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 01 Apr 2012 04:24:04 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_a_=22Hardware_c?= =?utf8?q?locks=22_section?= Message-ID: http://hg.python.org/peps/rev/7010ff8e845d changeset: 4182:7010ff8e845d user: Victor Stinner date: Sun Apr 01 04:03:15 2012 +0200 summary: PEP 418: Add a "Hardware clocks" section * Mention the QueryPerformanceCounter() issue on CPU with variable frequency files: pep-0418.txt | 46 +++++++++++++++++++++++++++++++++++---- 1 files changed, 41 insertions(+), 5 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -209,8 +209,30 @@ highres.use_monotonic = hasattr(time, 'monotonic') -Clocks -====== +Hardware clocks +=============== + +* HPET: An HPET chip consists of a 64-bit up-counter (main counter) + counting at least at 10 MHz and a set of up to 256 comparators (at + least 3). Each HPET can have up to 32 timers. +* TSC (Time Stamp Counter): Historically, the TSC increased with every internal + processor clock cycle, but now the rate is usually constant (even if the + processor changes frequency) and usually equals the maximum processor + frequency. The instructor RDTSC can be used to read this counter. +* ACPI PMTMR (power management timer): ACPI 24-bit timer with a frequency + of 3.5 MHz (3,579,545 Hz). HPET can cause around 3 seconds of drift per day. +* Cyclone: The Cyclone timer uses a 32-bit counter on IBM Extended + X-Architecture (EXA) chipsets which include computers that use the + IBM "Summit" series chipsets (ex: x440). This is available in IA32 + and IA64 architectures. +* PIT (programmable interrupt timer): Intel 8253/8254 chipsets with a + configurable frequency in range 18.2 Hz - 1.2 MHz. It is a 16-bit counter. +* RTC (Real-time clock). Most RTCs use a crystal oscillator with a frequency of + 32,768 Hz + + +Operating system clocks +======================= Monotonic clocks ---------------- @@ -363,6 +385,8 @@ * Windows XP had a bug (see `KB896256`_): on a multiprocessor computer, QueryPerformanceCounter() returned a different value for each processor. The bug was fixed in Windows XP SP2. +* Issues with processor with variable frequency: the frequency is changed + depending on the workload to reduce memory consumption. .. _KB896256: http://support.microsoft.com/?id=896256 .. _KB274323: http://support.microsoft.com/?id=274323 @@ -390,6 +414,11 @@ There are applications using this undocumented function, example: `Timer Resolution `_. +WaitForSingleObject() use the same timer than GetTickCount() with the same +resolution. + +GetTickCount() has an accuracy of 55 ms on Windows 9x. + Windows: timeGetTime ^^^^^^^^^^^^^^^^^^^^ @@ -610,19 +639,25 @@ Alternatives: API design ======================== -Name of the "monotonic or fallback" function name -------------------------------------------------- +Other names for new functions +----------------------------- -Other names were proposed: +time.highres(): * time.hires(): "hires" can be read as "to hire" as in "he hires a car to go on holiday", rather than a "HIgh-RESolution clock". +* time.timer(): "it would be too easy to confuse with (or misspell as) + time.time()" + +time.monotonic(): + * time.steady(): no OS provides a clock advancing at a steady rate, so "steady" should be avoided. * time.try_monotonic(): it is a clear and obvious solution for the use-case of "I prefer the monotonic clock, if it is available, otherwise I'll take my chances with a best-effect clock." -* time.wallclock() +* time.wallclock(): it is not the system time aka the "wall clock", but + a monotonic clock with an unspecified starting point One function, no flag -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 1 04:30:19 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 01 Apr 2012 04:30:19 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_time=2Eget=5Fclock?= =?utf8?q?=5Finfo=28=29=2C_rename_=22monotonic=22_option_to_=22is=5Fmonoto?= =?utf8?q?nic=22?= Message-ID: http://hg.python.org/peps/rev/4b3e9b3e37ba changeset: 4185:4b3e9b3e37ba user: Victor Stinner date: Sun Apr 01 04:30:13 2012 +0200 summary: PEP 418: time.get_clock_info(), rename "monotonic" option to "is_monotonic" files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -214,7 +214,7 @@ * "function" (str): name of the underlying operating system function (ex: "QueryPerformanceCounter()" or "clock_gettime(CLOCK_REALTIME)") * "resolution" (float): resolution in seconds of the function - * "monotonic" (bool): True if the clock is monotonic + * "is_monotonic" (bool): True if the clock is monotonic Hardware clocks -- Repository URL: http://hg.python.org/peps From ncoghlan at gmail.com Sun Apr 1 05:33:36 2012 From: ncoghlan at gmail.com (Nick Coghlan) Date: Sun, 1 Apr 2012 13:33:36 +1000 Subject: [Python-checkins] cpython: Issue #14435: Add Misc/NEWS and Misc/ACKS In-Reply-To: References: Message-ID: On Sat, Mar 31, 2012 at 11:10 PM, kristjan.jonsson wrote: > diff --git a/Misc/ACKS b/Misc/ACKS > --- a/Misc/ACKS > +++ b/Misc/ACKS > @@ -507,6 +507,7 @@ > ?Richard Jones > ?Irmen de Jong > ?Lucas de Jonge > +Kristj?n Valur J?nsson > ?Jens B. Jorgensen > ?John Jorgensen > ?Sijin Joseph *blinks* This must have been one of those cases where everyone assumed your name was already there and never thought to check... Cheers, Nick. -- Nick Coghlan?? |?? ncoghlan at gmail.com?? |?? Brisbane, Australia From solipsis at pitrou.net Sun Apr 1 05:35:02 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 01 Apr 2012 05:35:02 +0200 Subject: [Python-checkins] Daily reference leaks (51b5f2b90df2): sum=-6 Message-ID: results for 51b5f2b90df2 on branch "default" -------------------------------------------- test_xml_etree_c leaked [-2, -2, -2] references, sum=-6 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogovYOZv', '-x'] From python-checkins at python.org Sun Apr 1 09:20:09 2012 From: python-checkins at python.org (ned.deily) Date: Sun, 01 Apr 2012 09:20:09 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313507=3A_OS_X_inst?= =?utf8?q?aller_builds_now_build_liblzma_for_the_new?= Message-ID: http://hg.python.org/cpython/rev/0e1177499762 changeset: 76039:0e1177499762 user: Ned Deily date: Sun Apr 01 00:17:33 2012 -0700 summary: Issue #13507: OS X installer builds now build liblzma for the new lzma module. (Patch by Nicholas Riley) files: Mac/BuildScript/build-installer.py | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -143,6 +143,17 @@ def library_recipes(): result = [] + result.extend([ + dict( + name="XZ 5.0.3", + url="http://tukaani.org/xz/xz-5.0.3.tar.gz", + checksum='fefe52f9ecd521de2a8ce38c21a27574', + configure_pre=[ + '--disable-dependency-tracking', + ] + ) + ]) + if DEPTARGET < '10.5': result.extend([ dict( -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 11:31:41 2012 From: python-checkins at python.org (ned.deily) Date: Sun, 01 Apr 2012 11:31:41 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314463=3A_Prevent_?= =?utf8?q?=5Fdecimal=2Eso_compile_failures_in_OS_X_installer_builds=2E?= Message-ID: http://hg.python.org/cpython/rev/ac60138522fc changeset: 76040:ac60138522fc user: Ned Deily date: Sun Apr 01 02:30:46 2012 -0700 summary: Issue #14463: Prevent _decimal.so compile failures in OS X installer builds. files: setup.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1804,7 +1804,11 @@ sources = ['_decimal/_decimal.c'] depends = ['_decimal/docstrings.h'] else: - include_dirs = ['./Modules/_decimal/libmpdec'] + srcdir = sysconfig.get_config_var('srcdir') + include_dirs = [os.path.abspath(os.path.join(srcdir, + 'Modules', + '_decimal', + 'libmpdec'))] libraries = [] sources = [ '_decimal/_decimal.c', -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 13:08:48 2012 From: python-checkins at python.org (stefan.krah) Date: Sun, 01 Apr 2012 13:08:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314394=3A_Use_elabo?= =?utf8?q?rate_phrases_that_boil_down_to_=22one_to_two_orders?= Message-ID: http://hg.python.org/cpython/rev/6ba569924986 changeset: 76041:6ba569924986 user: Stefan Krah date: Sun Apr 01 13:07:24 2012 +0200 summary: Issue #14394: Use elaborate phrases that boil down to "one to two orders of magnitude". Provide link to the benchmarks. files: Doc/whatsnew/3.3.rst | 14 ++++++++++---- 1 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -603,11 +603,17 @@ C-module and libmpdec written by Stefan Krah. The new C version of the decimal module integrates the high speed libmpdec -library for arbitrary precision correctly-rounded decimal arithmetic. -libmpdec conforms to IBM's General Decimal Arithmetic Specification. +library for arbitrary precision correctly-rounded decimal floating point +arithmetic. libmpdec conforms to IBM's General Decimal Arithmetic Specification. -Performance gains range from 12x for database applications to 80x for -numerically intensive applications: +Performance gains range from 10x for database applications to 80x for +numerically intensive applications. These numbers are expected gains +for standard precisions used in decimal floating point arithmetic. Since +the precision is user configurable, the exact figures may vary. For example, +in integer bignum arithmetic the differences can be significantly higher. + +The following table is meant as an illustration. Benchmarks are available +at (http://www.bytereef.org/mpdecimal/quickstart.html). +---------+-------------+--------------+-------------+ | | decimal.py | _decimal | speedup | -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 13:10:52 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 01 Apr 2012 13:10:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Remove_parens_around_link?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/61f33da3185b changeset: 76042:61f33da3185b user: Georg Brandl date: Sun Apr 01 13:10:58 2012 +0200 summary: Remove parens around link. files: Doc/whatsnew/3.3.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -613,7 +613,7 @@ in integer bignum arithmetic the differences can be significantly higher. The following table is meant as an illustration. Benchmarks are available -at (http://www.bytereef.org/mpdecimal/quickstart.html). +at http://www.bytereef.org/mpdecimal/quickstart.html. +---------+-------------+--------------+-------------+ | | decimal.py | _decimal | speedup | -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 13:48:28 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 01 Apr 2012 13:48:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Update_pydoc_topics=2E?= Message-ID: http://hg.python.org/cpython/rev/707514c704e6 changeset: 76043:707514c704e6 user: Georg Brandl date: Sun Apr 01 13:46:44 2012 +0200 summary: Update pydoc topics. files: Lib/pydoc_data/topics.py | 12 ++++++------ 1 files changed, 6 insertions(+), 6 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 Mar 4 16:11:27 2012 +# Autogenerated by Sphinx on Sun Apr 1 13:46:17 2012 topics = {'assert': '\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\nto\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that ``__debug__`` and ``AssertionError``\nrefer to 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\n(command line option -O). The current code generator emits no code\nfor an assert statement when optimization is requested at compile\ntime. Note that it is unnecessary to include the source code for the\nexpression that failed in the error message; it will be displayed as\npart of the stack trace.\n\nAssignments to ``__debug__`` are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': '\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 the last three\nsymbols.)\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 object\n must be an iterable with the same number of items as there are\n targets in the target list, and the items are assigned, from left to\n right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an asterisk,\n called a "starred" target: The object must be a sequence with at\n least as many items as there are targets in the target list, minus\n one. The first items of the sequence are assigned, from left to\n right, to the targets before the starred target. The final items\n of the sequence are assigned to the targets after the starred\n target. A list of the remaining items in the sequence is then\n assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of items\n 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``\n statement in the current code block: the name is bound to the\n object in the current local namespace.\n\n * Otherwise: the name is bound to the object in the global namespace\n or the outer namespace determined by ``nonlocal``, 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 square\n brackets: The object must be an iterable with the same number of\n 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\n always set as an instance attribute, creating it if necessary.\n Thus, the two occurrences of ``a.x`` do not necessarily refer to the\n same attribute: if the RHS expression refers to a class attribute,\n the 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\n with appropriate arguments.\n\n* If the target is a slicing: The primary expression in the reference\n is evaluated. It should yield a mutable sequence object (such as a\n list). The assigned object should be a sequence object of the same\n type. Next, the lower and upper bound expressions are evaluated,\n insofar they are present; defaults are zero and the sequence\'s\n length. The bounds should evaluate to integers. If either bound is\n negative, the sequence\'s length is added to it. The resulting\n bounds are clipped to lie between zero and the sequence\'s length,\n inclusive. Finally, the sequence object is asked to replace the\n slice with the items of the assigned sequence. The length of the\n slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n 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\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample ``a, b = b, a`` swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints ``[0, 2]``:\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print(x)\n\nSee also:\n\n **PEP 3132** - Extended Iterable Unpacking\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 for 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\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\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': '\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 in front of the name, with leading underscores removed, and\na single underscore inserted in front of the class name. For example,\nthe identifier ``__spam`` occurring in a class named ``Ham`` will be\ntransformed to ``_Ham__spam``. This transformation is independent of\nthe syntactical context in which the identifier is used. If the\ntransformed name is extremely long (longer than 255 characters),\nimplementation defined truncation may happen. If the class name\nconsists only of underscores, no transformation is done.\n', @@ -19,12 +19,12 @@ 'calls': '\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\nA trailing comma may be present after the positional and keyword\narguments 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\n``TypeError`` exception is raised. Otherwise, the list of filled\nslots is used as the 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\nparse their 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\nformal parameter 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,\n``expression`` must evaluate to an iterable. Elements from this\niterable are treated as if they were additional positional arguments;\nif there are positional arguments *x1*, ..., *xN*, and ``expression``\nevaluates to a sequence *y1*, ..., *yM*, this is equivalent to a call\nwith M+N positional 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``\nsyntax to be used in the same call, so in practice this confusion does\nnot arise.\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,\na ``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\nan exception. 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\n the same as if that method was called.\n', 'class': '\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\n"``self.name``", and an instance attribute hides a class attribute\nwith the same name when accessed in this way. Class attributes can be\nused as defaults for instance attributes, but using mutable values\nthere can lead to unexpected results. *Descriptors* can be used to\ncreate instance variables with different implementation details.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3 **PEP 3129** - Class\n Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless there\n is a ``finally`` clause which happens to raise another exception.\n That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of an\n 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 function\n body is transformed into the function\'s ``__doc__`` attribute and\n 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', 'comparisons': '\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\nonly once (but in both cases ``z`` is not evaluated at all when ``x <\ny`` is found 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``,\nexcept that each expression is evaluated at most once.\n\nNote that ``a op1 b op2 c`` doesn\'t imply any kind of comparison\nbetween *a* and *c*, so that, e.g., ``x < y > z`` is perfectly legal\n(though perhaps not pretty).\n\nThe operators ``<``, ``>``, ``==``, ``>=``, ``<=``, and ``!=`` compare\nthe values of two objects. The objects need not have the same type.\nIf both are numbers, they are converted to a common type. Otherwise,\nthe ``==`` and ``!=`` operators *always* consider objects of different\ntypes to be unequal, while the ``<``, ``>``, ``>=`` and ``<=``\noperators raise a ``TypeError`` when comparing objects of different\ntypes that do not implement these operators for the given pair of\ntypes. You can control comparison behavior of objects of non-built-in\ntypes by defining rich comparison methods like ``__gt__()``, described\nin section *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. The\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 equivalents\n (the result of the built-in function ``ord()``) of their characters.\n [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison of\n 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\n same value as ``x <= y``. If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, ``[1,2] <\n [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\n undefined results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they are\n the same object; the choice whether one object is considered smaller\n or larger than another one is made arbitrarily but consistently\n within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another, but comparisons of\n``float`` and ``Decimal`` are not supported to avoid the inevitable\nconfusion arising from representation issues such as ``float(\'1.1\')``\nbeing inexactly represented and therefore not exactly equal to\n``Decimal(\'1.1\')`` which is. When cross-type comparison is not\nsupported, the comparison method returns ``NotImplemented``. This can\ncreate the illusion of non-transitivity between supported cross-type\ncomparisons and unsupported comparisons. For example, ``Decimal(2) ==\n2`` and ``2 == float(2)`` but ``Decimal(2) != float(2)``.\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``\ntests whether a the dictionary has a given key. For container types\nsuch as list, 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*\nis a substring of *y*. An equivalent test is ``y.find(x) != -1``.\nEmpty strings are always considered to be a substring of any other\nstring, so ``"" in "abc"`` will return ``True``.\n\nFor user-defined classes which define the ``__contains__()`` method,\n``x in 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\n== z`` is produced while iterating over ``y``. If an exception is\nraised during 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\ny`` is true if and only if *x* and *y* are the same object. ``x is\nnot y`` yields the inverse truth value. [4]\n', - 'compound': '\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\ncontrol flow constructs. ``try`` specifies exception handlers and/or\ncleanup code for a group of statements, while the ``with`` statement\nallows the execution of initialization and finalization code around a\nblock of code. Function and class definitions are also syntactically\ncompound statements.\n\nCompound statements consist 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 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 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\na ``DEDENT``. Also note that optional continuation clauses always\nbegin with 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\nexecuted and the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ngoes back to testing the expression.\n\n\nThe ``for`` statement\n=====================\n\nThe ``for`` statement is used to iterate over the elements of a\nsequence (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 of ascending indices. 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``\nexception), the suite in 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``\nstatement executed in the first suite skips the rest of the suite and\ncontinues with the next item, or with the ``else`` clause if there was\nno next item.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function ``range()`` returns an\niterator of integers suitable to emulate the effect of Pascal\'s ``for\ni := a to b do``; e.g., ``list(range(3))`` returns the list ``[0, 1,\n2]``.\n\nNote: There is a subtlety when the sequence is being modified by the loop\n (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" target]] ":" 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\nno exception occurs in the ``try`` clause, no exception handler is\nexecuted. When an exception occurs in the ``try`` suite, a search for\nan exception handler is started. This search inspects the except\nclauses in turn until one is found that matches the exception. An\nexpression-less except clause, if present, must be last; it matches\nany exception. For an except clause with an expression, that\nexpression is evaluated, and the clause matches the exception if the\nresulting object is "compatible" with the exception. An object is\ncompatible with an exception if it is the class or a base class of the\nexception object or a tuple containing an item compatible with the\nexception.\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\nraised the 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,\nif present, 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 access via\n``sys.exc_info()``. ``sys.exc_info()`` returns a 3-tuple consisting of\nthe exception class, the exception instance and a traceback object\n(see section *The standard type hierarchy*) identifying the point in\nthe program where the exception occurred. ``sys.exc_info()`` values\nare restored 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\nare not handled by the preceding ``except`` clauses.\n\nIf ``finally`` is present, it specifies a \'cleanup\' handler. The\n``try`` clause is executed, including any ``except`` and ``else``\nclauses. If an exception occurs in any of the clauses and is not\nhandled, the exception is temporarily saved. The ``finally`` clause is\nexecuted. If there is a saved exception, it is re-raised at the end\nof the ``finally`` clause. If the ``finally`` clause raises another\nexception or executes a ``return`` or ``break`` statement, the saved\nexception is set as the context of the new exception. The exception\ninformation is not available to the program during execution of the\n``finally`` clause.\n\nWhen a ``return``, ``break`` or ``continue`` statement is executed in\nthe ``try`` suite of a ``try``...``finally`` statement, the\n``finally`` clause is also executed \'on the way out.\' A ``continue``\nstatement is illegal in the ``finally`` clause. (The reason is a\nproblem with the current implementation --- this restriction may be\nlifted in the future).\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\n``try``...``except``...``finally`` usage patterns to be encapsulated\nfor 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\n be 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,\n three ``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\n reraised. If the return value was true, the exception is\n suppressed, and execution continues with the statement following\n the ``with`` 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:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` 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)*\n [, "**" 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 ---\nthis is a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, 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\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**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``"\nfollowing the parameter name. Any parameter may have an annotation\neven those of the form ``*identifier`` or ``**identifier``. Functions\nmay have "return" annotation of the form "``-> expression``" after the\nparameter list. These annotations can be any valid Python expression\nand are evaluated when the function definition is executed.\nAnnotations may be evaluated in a different order than they appear in\nthe source code. The presence of annotations does not change the\nsemantics of a function. The annotation values are available as\nvalues of a dictionary keyed by the parameters\' names in the\n``__annotations__`` attribute 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 forms,\ndescribed in section *Lambdas*. Note that the lambda form is merely a\nshorthand for a simplified function definition; a function defined in\na "``def``" statement can be passed around or assigned to another name\njust like a function defined by a lambda form. The "``def``" form is\nactually more powerful since it allows the execution of multiple\nstatements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\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\n"``self.name``", and an instance attribute hides a class attribute\nwith the same name when accessed in this way. Class attributes can be\nused as defaults for instance attributes, but using mutable values\nthere can lead to unexpected results. *Descriptors* can be used to\ncreate instance variables with different implementation details.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3 **PEP 3129** - Class\n Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless there\n is a ``finally`` clause which happens to raise another exception.\n That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of an\n 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 function\n body is transformed into the function\'s ``__doc__`` attribute and\n 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': '\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\ncontrol flow constructs. ``try`` specifies exception handlers and/or\ncleanup code for a group of statements, while the ``with`` statement\nallows the execution of initialization and finalization code around a\nblock of code. Function and class definitions are also syntactically\ncompound statements.\n\nCompound statements consist 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 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 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\na ``DEDENT``. Also note that optional continuation clauses always\nbegin with 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\nexecuted and the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ngoes back to testing the expression.\n\n\nThe ``for`` statement\n=====================\n\nThe ``for`` statement is used to iterate over the elements of a\nsequence (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 of ascending indices. 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``\nexception), the suite in 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``\nstatement executed in the first suite skips the rest of the suite and\ncontinues with the next item, or with the ``else`` clause if there was\nno next item.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function ``range()`` returns an\niterator of integers suitable to emulate the effect of Pascal\'s ``for\ni := a to b do``; e.g., ``list(range(3))`` returns the list ``[0, 1,\n2]``.\n\nNote: There is a subtlety when the sequence is being modified by the loop\n (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" target]] ":" 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\nno exception occurs in the ``try`` clause, no exception handler is\nexecuted. When an exception occurs in the ``try`` suite, a search for\nan exception handler is started. This search inspects the except\nclauses in turn until one is found that matches the exception. An\nexpression-less except clause, if present, must be last; it matches\nany exception. For an except clause with an expression, that\nexpression is evaluated, and the clause matches the exception if the\nresulting object is "compatible" with the exception. An object is\ncompatible with an exception if it is the class or a base class of the\nexception object or a tuple containing an item compatible with the\nexception.\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\nraised the 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,\nif present, 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 access via\n``sys.exc_info()``. ``sys.exc_info()`` returns a 3-tuple consisting of\nthe exception class, the exception instance and a traceback object\n(see section *The standard type hierarchy*) identifying the point in\nthe program where the exception occurred. ``sys.exc_info()`` values\nare restored 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\nare not handled by the preceding ``except`` clauses.\n\nIf ``finally`` is present, it specifies a \'cleanup\' handler. The\n``try`` clause is executed, including any ``except`` and ``else``\nclauses. If an exception occurs in any of the clauses and is not\nhandled, the exception is temporarily saved. The ``finally`` clause is\nexecuted. If there is a saved exception, it is re-raised at the end\nof the ``finally`` clause. If the ``finally`` clause raises another\nexception or executes a ``return`` or ``break`` statement, the saved\nexception is set as the context of the new exception. The exception\ninformation is not available to the program during execution of the\n``finally`` clause.\n\nWhen a ``return``, ``break`` or ``continue`` statement is executed in\nthe ``try`` suite of a ``try``...``finally`` statement, the\n``finally`` clause is also executed \'on the way out.\' A ``continue``\nstatement is illegal in the ``finally`` clause. (The reason is a\nproblem with the current implementation --- this restriction may be\nlifted in the future).\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\n``try``...``except``...``finally`` usage patterns to be encapsulated\nfor 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\n be 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,\n three ``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\n reraised. If the return value was true, the exception is\n suppressed, and execution continues with the statement following\n the ``with`` 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:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` 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)*\n [, "**" 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 ---\nthis is a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, 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\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**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``"\nfollowing the parameter name. Any parameter may have an annotation\neven those of the form ``*identifier`` or ``**identifier``. Functions\nmay have "return" annotation of the form "``-> expression``" after the\nparameter list. These annotations can be any valid Python expression\nand are evaluated when the function definition is executed.\nAnnotations may be evaluated in a different order than they appear in\nthe source code. The presence of annotations does not change the\nsemantics of a function. The annotation values are available as\nvalues of a dictionary keyed by the parameters\' names in the\n``__annotations__`` attribute 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 forms,\ndescribed in section *Lambdas*. Note that the lambda form is merely a\nshorthand for a simplified function definition; a function defined in\na "``def``" statement can be passed around or assigned to another name\njust like a function defined by a lambda form. The "``def``" form is\nactually more powerful since it allows the execution of multiple\nstatements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also:\n\n **PEP 3107** - Function Annotations\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\n"``self.name``", and an instance attribute hides a class attribute\nwith the same name when accessed in this way. Class attributes can be\nused as defaults for instance attributes, but using mutable values\nthere can lead to unexpected results. *Descriptors* can be used to\ncreate instance variables with different implementation details.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3 **PEP 3129** - Class\n Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless there\n is a ``finally`` clause which happens to raise another exception.\n That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of an\n 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 function\n body is transformed into the function\'s ``__doc__`` attribute and\n 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': '\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\nmanager handles the entry into, and the exit from, the desired runtime\ncontext for the execution of the block of code. Context managers are\nnormally invoked using the ``with`` statement (described in section\n*The with statement*), but can also be used by directly invoking their\nmethods.\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:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n', 'continue': '\nThe ``continue`` statement\n**************************\n\n continue_stmt ::= "continue"\n\n``continue`` may only occur syntactically nested in a ``for`` or\n``while`` loop, but not nested in a function or class definition or\n``finally`` clause within that loop. It continues with the next cycle\nof the nearest 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': '\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 that way:\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 other\n 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 left\nargument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', 'customization': '\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\n an 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 when the instance is created. 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,\n if any, must explicitly call it to ensure proper initialization of\n the base class part of the instance; for example:\n ``BaseClass.__init__(self, [args...])``. As a special constraint\n on constructors, no value may be returned; doing so will cause a\n ``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,\n the derived class\'s ``__del__()`` method, if any, must explicitly\n call it to ensure proper deletion of the base class part of the\n instance. Note that it is possible (though not recommended!) for\n the ``__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\n is only called when ``x``\'s reference count reaches zero. Some\n common situations that may prevent the reference count of an\n object from going to zero include: circular references between\n objects (e.g., a doubly-linked list or a tree data structure with\n parent and child pointers); a reference to the object on the\n stack frame of a function that caught an exception (the traceback\n stored in ``sys.exc_info()[2]`` keeps the stack frame alive); or\n a reference to the object on the stack frame that raised an\n unhandled 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 latter two situations can be resolved by storing ``None`` in\n ``sys.last_traceback``. Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level ``__del__()`` methods involved. Refer to the documentation\n for the ``gc`` module for more information about how\n ``__del__()`` methods are handled by the cycle detector,\n particularly the description of the ``garbage`` value.\n\n Warning: Due to the precarious circumstances under which ``__del__()``\n methods are invoked, exceptions that occur during their execution\n are ignored, and a warning is printed to ``sys.stderr`` instead.\n Also, when ``__del__()`` is invoked in response to a module being\n deleted (e.g., when execution of the program is done), other\n globals referenced by the ``__del__()`` method may already have\n been deleted or in the process of being torn down (e.g. the\n import machinery shutting down). For this reason, ``__del__()``\n methods should do the absolute minimum needed to maintain\n external invariants. Starting with version 1.5, Python\n 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\n "official" string representation of an object. If at all possible,\n this should look like a valid Python expression that could be used\n to 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__()``\n but not ``__str__()``, then ``__repr__()`` is also used when an\n "informal" string representation of instances of that class is\n 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 the ``str()`` built-in function and by the ``print()``\n function to compute the "informal" string representation of an\n object. This differs from ``__repr__()`` in that it does not have\n to be a valid Python expression: a more convenient or concise\n representation may be used instead. The return value must be a\n string object.\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 ``format()`` method of class ``str``) to produce a "formatted"\n string representation of an object. The ``format_spec`` argument is\n a string that contains a description of the formatting options\n desired. The interpretation of the ``format_spec`` argument is up\n to the type implementing ``__format__()``, however most classes\n will either delegate formatting to one of the built-in types, or\n use a 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\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 ``x.__gt__(y)``, and ``x>=y`` calls\n ``x.__ge__(y)``.\n\n A rich comparison method may return the singleton\n ``NotImplemented`` if it does not implement the operation for a\n given pair of arguments. By convention, ``False`` and ``True`` are\n returned for a successful comparison. However, these methods can\n return any value, so if the comparison operator is used in a\n Boolean context (e.g., in the condition of an ``if`` statement),\n Python will call ``bool()`` on the value to determine if the result\n 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\n the paragraph on ``__hash__()`` for some important notes on\n creating *hashable* objects which support custom comparison\n operations and 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\n other\'s reflection, ``__le__()`` and ``__ge__()`` are each other\'s\n reflection, and ``__eq__()`` and ``__ne__()`` are their own\n 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\n members of hashed collections including ``set``, ``frozenset``, and\n ``dict``. ``__hash__()`` should return an integer. The only\n required property is that objects which compare equal have the same\n hash value; it is advised to somehow mix together (e.g. using\n exclusive or) the hash values for the components of the object that\n also play a part in comparison of objects.\n\n If a class does not define an ``__eq__()`` method it should not\n define a ``__hash__()`` operation either; if it defines\n ``__eq__()`` but not ``__hash__()``, its instances will not be\n usable as items in hashable collections. If a class defines\n mutable objects and implements an ``__eq__()`` method, it should\n not implement ``__hash__()``, since the implementation of hashable\n collections requires that a key\'s hash value is immutable (if the\n object\'s hash value changes, it will be in the wrong hash bucket).\n\n User-defined classes have ``__eq__()`` and ``__hash__()`` methods\n by default; with them, all objects compare unequal (except with\n themselves) and ``x.__hash__()`` returns ``id(x)``.\n\n Classes which inherit a ``__hash__()`` method from a parent class\n but change the meaning of ``__eq__()`` such that the hash value\n returned is no longer appropriate (e.g. by switching to a value-\n based concept of equality instead of the default identity based\n equality) can explicitly flag themselves as being unhashable by\n setting ``__hash__ = None`` in the class definition. Doing so means\n that not only will instances of the class raise an appropriate\n ``TypeError`` when a program attempts to retrieve their hash value,\n but they will also be correctly identified as unhashable when\n checking ``isinstance(obj, collections.Hashable)`` (unlike classes\n which define their own ``__hash__()`` to explicitly raise\n ``TypeError``).\n\n If a class that overrides ``__eq__()`` needs to retain the\n implementation of ``__hash__()`` from a parent class, the\n interpreter must be told this explicitly by setting ``__hash__ =\n .__hash__``. Otherwise the inheritance of\n ``__hash__()`` will be blocked, just as if ``__hash__`` had been\n explicitly set to ``None``.\n\n Note: 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 order in which keys are\n retrieved from a dict. Note 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\n is not defined, ``__len__()`` is called, if it is defined, and the\n object is considered true if its result is nonzero. If a class\n defines neither ``__len__()`` nor ``__bool__()``, all its instances\n are considered true.\n', - 'debugger': '\n``pdb`` --- The Python Debugger\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\nreading the source. The extension interface uses the modules ``bdb``\nand ``cmd``.\n\nThe debugger\'s prompt is ``(Pdb)``. Typical usage to run a program\nunder control 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\n``pdb.py`` can also be invoked as a script to debug other scripts.\nFor example:\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\nexecutes commands as if given in a ``.pdbrc`` file, see *Debugger\nCommands*.\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\n the explanation of the built-in ``exec()`` or ``eval()``\n 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\ninstantiating the ``Pdb`` class and calling the method of the same\nname. If you want to access further features, you have to do this\nyourself:\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\nthe help command (but not ``he`` or ``hel``, nor ``H`` or ``Help`` or\n``HELP``). Arguments to commands must be separated by whitespace\n(spaces or tabs). Optional arguments are enclosed in square brackets\n(``[]``) in the 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\nmultiple commands in a line that is passed to the Python parser.) No\nintelligence is applied to separating the commands; the input is split\nat the first ``;;`` pair, even if it is in the middle of a quoted\nstring.\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,\nthese commands 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,\n ``help 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) print 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\n ``step`` is that ``step`` stops inside a called function, while\n ``next`` executes called functions at (nearly) full speed, only\n stopping at 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.\n With 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\n an exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ``>>``, if it\n differs 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(rint) expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\npp expression\n\n Like the ``print`` command, except the value of the expression is\n pretty-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\n all 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\n are 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 is\n determined by the ``__name__`` in the frame globals.\n', + 'debugger': '\n``pdb`` --- The Python Debugger\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\nreading the source. The extension interface uses the modules ``bdb``\nand ``cmd``.\n\nThe debugger\'s prompt is ``(Pdb)``. Typical usage to run a program\nunder control 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 ``print`` command.\n\n``pdb.py`` can also be invoked as a script to debug other scripts.\nFor example:\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\nexecutes commands as if given in a ``.pdbrc`` file, see *Debugger\nCommands*.\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\n the explanation of the built-in ``exec()`` or ``eval()``\n 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\ninstantiating the ``Pdb`` class and calling the method of the same\nname. If you want to access further features, you have to do this\nyourself:\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\nthe help command (but not ``he`` or ``hel``, nor ``H`` or ``Help`` or\n``HELP``). Arguments to commands must be separated by whitespace\n(spaces or tabs). Optional arguments are enclosed in square brackets\n(``[]``) in the 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\nmultiple commands in a line that is passed to the Python parser.) No\nintelligence is applied to separating the commands; the input is split\nat the first ``;;`` pair, even if it is in the middle of a quoted\nstring.\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,\nthese commands 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,\n ``help 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) print 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\n ``step`` is that ``step`` stops inside a called function, while\n ``next`` executes called functions at (nearly) full speed, only\n stopping at 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.\n With 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\n an exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ``>>``, if it\n differs 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(rint) expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\npp expression\n\n Like the ``print`` command, except the value of the expression is\n pretty-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\n all 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\n are 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 is\n determined by the ``__name__`` in the frame globals.\n', 'del': '\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.\n', 'dict': '\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': '\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\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\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', @@ -35,7 +35,7 @@ 'floating': '\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\nnumber as ``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': '\nThe ``for`` statement\n*********************\n\nThe ``for`` statement is used to iterate over the elements of a\nsequence (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 of ascending indices. 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``\nexception), the suite in 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``\nstatement executed in the first suite skips the rest of the suite and\ncontinues with the next item, or with the ``else`` clause if there was\nno next item.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function ``range()`` returns an\niterator of integers suitable to emulate the effect of Pascal\'s ``for\ni := a to b do``; e.g., ``list(range(3))`` returns the list ``[0, 1,\n2]``.\n\nNote: There is a subtlety when the sequence is being modified by the loop\n (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', 'formatstrings': '\nFormat String Syntax\n********************\n\nThe ``str.format()`` method and the ``Formatter`` class share the same\nsyntax for format strings (although in the case of ``Formatter``,\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n``{}``. Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n``{{`` and ``}}``.\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s" | "a"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point ``\'!\'``, and a *format_spec*, which\nis preceded by a colon ``\':\'``. These specify a non-default format\nfor the replacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings ``\'10\'`` or\n``\':-]\'``) within a format string. The *arg_name* can be followed by\nany number of index or attribute expressions. An expression of the\nform ``\'.name\'`` selects the named attribute using ``getattr()``,\nwhile an expression of the form ``\'[index]\'`` does an index lookup\nusing ``__getitem__()``.\n\nChanged in version 3.1: The positional argument specifiers can be\nomitted, so ``\'{} {}\'`` is equivalent to ``\'{0} {1}\'``.\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the\n``__format__()`` method of the value itself. However, in some cases\nit is desirable to force a type to be formatted as a string,\noverriding its own definition of formatting. By converting the value\nto a string before calling ``__format__()``, the normal formatting\nlogic is bypassed.\n\nThree conversion flags are currently supported: ``\'!s\'`` which calls\n``str()`` on the value, ``\'!r\'`` which calls ``repr()`` and ``\'!a\'``\nwhich calls ``ascii()``.\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n "More {!a}" # Calls ascii() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in ``format()`` function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string (``""``) produces\nthe same result as if you had called ``str()`` on the value. A non-\nempty format string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nThe *fill* character can be any character other than \'{\' or \'}\'. The\npresence of a fill character is signaled by the character following\nit, which must be one of the alignment options. If the second\ncharacter of *format_spec* is not a valid alignment option, then it is\nassumed that both the fill character and the alignment option are\nabsent.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'<\'`` | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | ``\'>\'`` | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | ``\'=\'`` | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. |\n +-----------+------------------------------------------------------------+\n | ``\'^\'`` | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'+\'`` | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | ``\'-\'`` | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe ``\'#\'`` option causes the "alternate form" to be used for the\nconversion. The alternate form is defined differently for different\ntypes. This option is only valid for integer, float, complex and\nDecimal types. For integers, when binary, octal, or hexadecimal output\nis used, this option adds the prefix respective ``\'0b\'``, ``\'0o\'``, or\n``\'0x\'`` to the output value. For floats, complex and Decimal the\nalternate form causes the result of the conversion to always contain a\ndecimal-point character, even if no digits follow it. Normally, a\ndecimal-point character appears in the result of these conversions\nonly if a digit follows it. In addition, for ``\'g\'`` and ``\'G\'``\nconversions, trailing zeros are not removed from the result.\n\nThe ``\',\'`` option signals the use of a comma for a thousands\nseparator. For a locale aware separator, use the ``\'n\'`` integer\npresentation type instead.\n\nChanged in version 3.1: Added the ``\',\'`` option (see also **PEP\n378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nIf the *width* field is preceded by a zero (``\'0\'``) character, this\nenables zero-padding. This is equivalent to an *alignment* type of\n``\'=\'`` and a *fill* character of ``\'0\'``.\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with ``\'f\'`` and ``\'F\'``, or before and after the decimal\npoint for a floating point value formatted with ``\'g\'`` or ``\'G\'``.\nFor non-number types the field indicates the maximum field size - in\nother words, how many characters will be used from the field content.\nThe *precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'s\'`` | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'s\'``. |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'b\'`` | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | ``\'c\'`` | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | ``\'d\'`` | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | ``\'o\'`` | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | ``\'x\'`` | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'X\'`` | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'d\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'d\'``. |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except\n``\'n\'`` and None). When doing so, ``float()`` is used to convert the\ninteger to a floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'e\'`` | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n +-----------+------------------------------------------------------------+\n | ``\'E\'`` | Exponent notation. Same as ``\'e\'`` except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | ``\'f\'`` | Fixed point. Displays the number as a fixed-point number. |\n +-----------+------------------------------------------------------------+\n | ``\'F\'`` | Fixed point. Same as ``\'f\'``, but converts ``nan`` to |\n | | ``NAN`` and ``inf`` to ``INF``. |\n +-----------+------------------------------------------------------------+\n | ``\'g\'`` | General format. For a given precision ``p >= 1``, this |\n | | rounds the number to ``p`` significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1`` would have exponent ``exp``. Then if ``-4 <= exp |\n | | < p``, the number is formatted with presentation type |\n | | ``\'f\'`` and precision ``p-1-exp``. Otherwise, the number |\n | | is formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1``. In both cases insignificant trailing zeros are |\n | | removed from the significand, and the decimal point is |\n | | also removed if there are no remaining digits following |\n | | it. Positive and negative infinity, positive and negative |\n | | zero, and nans, are formatted as ``inf``, ``-inf``, ``0``, |\n | | ``-0`` and ``nan`` respectively, regardless of the |\n | | precision. A precision of ``0`` is treated as equivalent |\n | | to a precision of ``1``. |\n +-----------+------------------------------------------------------------+\n | ``\'G\'`` | General format. Same as ``\'g\'`` except switches to ``\'E\'`` |\n | | if the number gets too large. The representations of |\n | | infinity and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'g\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | ``\'%\'`` | Percentage. Multiplies the number by 100 and displays in |\n | | fixed (``\'f\'``) format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | Similar to ``\'g\'``, except with at least one digit past |\n | | the decimal point and a default precision of 12. This is |\n | | intended to match ``str()``, except you can add the other |\n | | format modifiers. |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old ``%``-formatting.\n\nIn most of the cases the syntax is similar to the old\n``%``-formatting, with the addition of the ``{}`` and with ``:`` used\ninstead of ``%``. For example, ``\'%03.2f\'`` can be translated to\n``\'{:03.2f}\'``.\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 3.1+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point:\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing ``%s`` and ``%r``:\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing ``%x`` and ``%o`` and converting the value to different\nbases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 86.36%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12):\n ... for base in \'dXob\':\n ... print(\'{0:{width}{base}}\'.format(num, base=base, width=width), end=\' \')\n ... print()\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', - 'function': '\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)*\n [, "**" 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 ---\nthis is a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, 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\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**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``"\nfollowing the parameter name. Any parameter may have an annotation\neven those of the form ``*identifier`` or ``**identifier``. Functions\nmay have "return" annotation of the form "``-> expression``" after the\nparameter list. These annotations can be any valid Python expression\nand are evaluated when the function definition is executed.\nAnnotations may be evaluated in a different order than they appear in\nthe source code. The presence of annotations does not change the\nsemantics of a function. The annotation values are available as\nvalues of a dictionary keyed by the parameters\' names in the\n``__annotations__`` attribute 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 forms,\ndescribed in section *Lambdas*. Note that the lambda form is merely a\nshorthand for a simplified function definition; a function defined in\na "``def``" statement can be passed around or assigned to another name\njust like a function defined by a lambda form. The "``def``" form is\nactually more powerful since it allows the execution of multiple\nstatements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n', + 'function': '\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)*\n [, "**" 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 ---\nthis is a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, 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\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**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``"\nfollowing the parameter name. Any parameter may have an annotation\neven those of the form ``*identifier`` or ``**identifier``. Functions\nmay have "return" annotation of the form "``-> expression``" after the\nparameter list. These annotations can be any valid Python expression\nand are evaluated when the function definition is executed.\nAnnotations may be evaluated in a different order than they appear in\nthe source code. The presence of annotations does not change the\nsemantics of a function. The annotation values are available as\nvalues of a dictionary keyed by the parameters\' names in the\n``__annotations__`` attribute 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 forms,\ndescribed in section *Lambdas*. Note that the lambda form is merely a\nshorthand for a simplified function definition; a function defined in\na "``def``" statement can be passed around or assigned to another name\njust like a function defined by a lambda form. The "``def``" form is\nactually more powerful since it allows the execution of multiple\nstatements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also:\n\n **PEP 3107** - Function Annotations\n The original specification for function annotations.\n', 'global': '\nThe ``global`` statement\n************************\n\n global_stmt ::= "global" identifier ("," identifier)*\n\nThe ``global`` statement is a declaration which holds for the entire\ncurrent code block. It means that the listed identifiers are to be\ninterpreted as globals. It would be impossible to assign to a global\nvariable without ``global``, although free variables may refer to\nglobals without being declared global.\n\nNames listed in a ``global`` statement must not be used in the same\ncode block textually preceding that ``global`` statement.\n\nNames listed in a ``global`` statement must not be defined as formal\nparameters or in a ``for`` loop control target, ``class`` definition,\nfunction definition, or ``import`` statement.\n\n**CPython implementation detail:** The current implementation does not\nenforce the latter two restrictions, but programs should not abuse\nthis freedom, as future implementations may enforce them or silently\nchange the meaning of the program.\n\n**Programmer\'s note:** the ``global`` is a directive to the parser.\nIt applies only to code parsed at the same time as the ``global``\nstatement. In particular, a ``global`` statement contained in a string\nor code object supplied to the built-in ``exec()`` function does not\naffect the code block *containing* the function call, and code\ncontained in such a string is unaffected by ``global`` statements in\nthe code containing the function call. The same applies to the\n``eval()`` and ``compile()`` functions.\n', 'id-classes': '\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n``_*``\n Not imported by ``from module import *``. The special identifier\n ``_`` is used in the interactive interpreter to store the result of\n the last evaluation; it is stored in the ``builtins`` module. When\n not in interactive mode, ``_`` has no special meaning and is not\n defined. See section *The import statement*.\n\n Note: The name ``_`` is often used in conjunction with\n internationalization; refer to the documentation for the\n ``gettext`` module for more information on this convention.\n\n``__*__``\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of ``__*__`` names, in any context, that does\n not follow explicitly documented use, is subject to breakage\n without warning.\n\n``__*``\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', 'identifiers': '\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions.\n\nThe syntax of identifiers in Python is based on the Unicode standard\nannex UAX-31, with elaboration and changes as defined below; see also\n**PEP 3131** for further details.\n\nWithin the ASCII range (U+0001..U+007F), the valid characters for\nidentifiers are the same as in Python 2.x: the uppercase and lowercase\nletters ``A`` through ``Z``, the underscore ``_`` and, except for the\nfirst character, the digits ``0`` through ``9``.\n\nPython 3.0 introduces additional characters from outside the ASCII\nrange (see **PEP 3131**). For these characters, the classification\nuses the version of the Unicode Character Database as included in the\n``unicodedata`` module.\n\nIdentifiers are unlimited in length. Case is significant.\n\n identifier ::= xid_start xid_continue*\n id_start ::= \n id_continue ::= \n xid_start ::= \n xid_continue ::= \n\nThe Unicode category codes mentioned above stand for:\n\n* *Lu* - uppercase letters\n\n* *Ll* - lowercase letters\n\n* *Lt* - titlecase letters\n\n* *Lm* - modifier letters\n\n* *Lo* - other letters\n\n* *Nl* - letter numbers\n\n* *Mn* - nonspacing marks\n\n* *Mc* - spacing combining marks\n\n* *Nd* - decimal numbers\n\n* *Pc* - connector punctuations\n\n* *Other_ID_Start* - explicit list of characters in PropList.txt to\n support backwards compatibility\n\n* *Other_ID_Continue* - likewise\n\nAll identifiers are converted into the normal form NFKC while parsing;\ncomparison of identifiers is based on NFKC.\n\nA non-normative HTML file listing all valid identifier characters for\nUnicode 4.1 can be found at http://www.dcl.hpi.uni-\npotsdam.de/home/loewis/table-3131.html.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n False class finally is return\n None continue for lambda try\n True def from nonlocal while\n and del global not with\n as elif if or yield\n assert else import pass\n break except in raise\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n``_*``\n Not imported by ``from module import *``. The special identifier\n ``_`` is used in the interactive interpreter to store the result of\n the last evaluation; it is stored in the ``builtins`` module. When\n not in interactive mode, ``_`` has no special meaning and is not\n defined. See section *The import statement*.\n\n Note: The name ``_`` is often used in conjunction with\n internationalization; refer to the documentation for the\n ``gettext`` module for more information on this convention.\n\n``__*__``\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of ``__*__`` names, in any context, that does\n not follow explicitly documented use, is subject to breakage\n without warning.\n\n``__*``\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', @@ -68,10 +68,10 @@ 'try': '\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" target]] ":" 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\nno exception occurs in the ``try`` clause, no exception handler is\nexecuted. When an exception occurs in the ``try`` suite, a search for\nan exception handler is started. This search inspects the except\nclauses in turn until one is found that matches the exception. An\nexpression-less except clause, if present, must be last; it matches\nany exception. For an except clause with an expression, that\nexpression is evaluated, and the clause matches the exception if the\nresulting object is "compatible" with the exception. An object is\ncompatible with an exception if it is the class or a base class of the\nexception object or a tuple containing an item compatible with the\nexception.\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\nraised the 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,\nif present, 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 access via\n``sys.exc_info()``. ``sys.exc_info()`` returns a 3-tuple consisting of\nthe exception class, the exception instance and a traceback object\n(see section *The standard type hierarchy*) identifying the point in\nthe program where the exception occurred. ``sys.exc_info()`` values\nare restored 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\nare not handled by the preceding ``except`` clauses.\n\nIf ``finally`` is present, it specifies a \'cleanup\' handler. The\n``try`` clause is executed, including any ``except`` and ``else``\nclauses. If an exception occurs in any of the clauses and is not\nhandled, the exception is temporarily saved. The ``finally`` clause is\nexecuted. If there is a saved exception, it is re-raised at the end\nof the ``finally`` clause. If the ``finally`` clause raises another\nexception or executes a ``return`` or ``break`` statement, the saved\nexception is set as the context of the new exception. The exception\ninformation is not available to the program during execution of the\n``finally`` clause.\n\nWhen a ``return``, ``break`` or ``continue`` statement is executed in\nthe ``try`` suite of a ``try``...``finally`` statement, the\n``finally`` clause is also executed \'on the way out.\' A ``continue``\nstatement is illegal in the ``finally`` clause. (The reason is a\nproblem with the current implementation --- this restriction may be\nlifted in the future).\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', 'types': '\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name ``None``.\n It is used to signify the absence of a value in many situations,\n e.g., it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n ``NotImplemented``. Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal ``...`` or the\n built-in name ``Ellipsis``. Its truth value is true.\n\n``numbers.Number``\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n ``numbers.Integral``\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers (``int``)\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans (``bool``)\n These represent the truth values False and True. The two\n objects representing the values False and True are the only\n Boolean objects. The Boolean type is a subtype of the integer\n type, and Boolean values behave like the values 0 and 1,\n respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ``"False"`` or\n ``"True"`` are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n ``numbers.Real`` (``float``)\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these is\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n ``numbers.Complex`` (``complex``)\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number ``z`` can be retrieved through the read-only\n attributes ``z.real`` and ``z.imag``.\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function ``len()`` returns the number of\n items of a sequence. When the length of a sequence is *n*, the\n index set contains the numbers 0, 1, ..., *n*-1. Item *i* of\n sequence *a* is selected by ``a[i]``.\n\n Sequences also support slicing: ``a[i:j]`` selects all items with\n index *k* such that *i* ``<=`` *k* ``<`` *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: ``a[i:j:k]`` selects all items of *a* with index *x*\n where ``x = i + n*k``, *n* ``>=`` ``0`` and *i* ``<=`` *x* ``<``\n *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode\n codepoints. All the codepoints in range ``U+0000 - U+10FFFF``\n can be represented in a string. Python doesn\'t have a\n ``chr`` type, and every character in the string is\n represented as a string object with length ``1``. The built-\n in function ``ord()`` converts a character to its codepoint\n (as an integer); ``chr()`` converts an integer in range ``0 -\n 10FFFF`` to the corresponding character. ``str.encode()`` can\n be used to convert a ``str`` to ``bytes`` using the given\n encoding, and ``bytes.decode()`` can be used to achieve the\n opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like ``b\'abc\'`` and the built-in function\n ``bytes()`` can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the ``decode()``\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and ``del`` (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in ``bytearray()`` constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module ``array`` provides an additional example of\n a mutable sequence type, as does the ``collections`` module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function ``len()``\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n ``set()`` constructor and can be modified afterwards by several\n methods, such as ``add()``.\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in ``frozenset()`` constructor. As a frozenset is\n immutable and *hashable*, it can be used again as an element of\n another set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation ``a[k]`` selects the item indexed by\n ``k`` from the mapping ``a``; this can be used in expressions and\n as the target of assignments or ``del`` statements. The built-in\n function ``len()`` returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``) then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the ``{...}``\n notation (see section *Dictionary displays*).\n\n The extension modules ``dbm.ndbm`` and ``dbm.gnu`` provide\n additional examples of mapping types, as does the\n ``collections`` module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +===========================+=================================+=============+\n | ``__doc__`` | The function\'s documentation | Writable |\n | | string, or ``None`` if | |\n | | unavailable | |\n +---------------------------+---------------------------------+-------------+\n | ``__name__`` | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | ``__qualname__`` | The function\'s *qualified name* | Writable |\n | | New in version 3.3. | |\n +---------------------------+---------------------------------+-------------+\n | ``__module__`` | The name of the module the | Writable |\n | | function was defined in, or | |\n | | ``None`` if unavailable. | |\n +---------------------------+---------------------------------+-------------+\n | ``__defaults__`` | A tuple containing default | Writable |\n | | argument values for those | |\n | | arguments that have defaults, | |\n | | or ``None`` if no arguments | |\n | | have a default value | |\n +---------------------------+---------------------------------+-------------+\n | ``__code__`` | The code object representing | Writable |\n | | the compiled function body. | |\n +---------------------------+---------------------------------+-------------+\n | ``__globals__`` | A reference to the dictionary | Read-only |\n | | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +---------------------------+---------------------------------+-------------+\n | ``__dict__`` | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +---------------------------+---------------------------------+-------------+\n | ``__closure__`` | ``None`` or a tuple of cells | Read-only |\n | | that contain bindings for the | |\n | | function\'s free variables. | |\n +---------------------------+---------------------------------+-------------+\n | ``__annotations__`` | A dict containing annotations | Writable |\n | | of parameters. The keys of the | |\n | | dict are the parameter names, | |\n | | or ``\'return\'`` for the return | |\n | | annotation, if provided. | |\n +---------------------------+---------------------------------+-------------+\n | ``__kwdefaults__`` | A dict containing defaults for | Writable |\n | | keyword-only parameters. | |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: ``__self__`` is the class instance\n object, ``__func__`` is the function object; ``__doc__`` is the\n method\'s documentation (same as ``__func__.__doc__``);\n ``__name__`` is the method name (same as ``__func__.__name__``);\n ``__module__`` is the name of the module the method was defined\n in, or ``None`` if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its ``__self__`` attribute is the instance, and the method\n object is said to be bound. The new method\'s ``__func__``\n attribute is the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the ``__func__``\n attribute of the new instance is not the original method object\n but its ``__func__`` attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its ``__self__``\n attribute is the class itself, and its ``__func__`` attribute is\n the function object underlying the class method.\n\n When an instance method object is called, the underlying\n function (``__func__``) is called, inserting the class instance\n (``__self__``) in front of the argument list. For instance,\n when ``C`` is a class which contains a definition for a function\n ``f()``, and ``x`` is an instance of ``C``, calling ``x.f(1)``\n is equivalent to calling ``C.f(x, 1)``.\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in ``__self__`` will\n actually be the class itself, so that calling either ``x.f(1)``\n or ``C.f(1)`` is equivalent to calling ``f(C,1)`` where ``f`` is\n the underlying function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the ``yield`` statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s ``__next__()`` method will cause the function to\n execute until it provides a value using the ``yield`` statement.\n When the function executes a ``return`` statement or falls off\n the end, a ``StopIteration`` exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are ``len()`` and ``math.sin()``\n (``math`` is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: ``__doc__`` is the function\'s documentation\n string, or ``None`` if unavailable; ``__name__`` is the\n function\'s name; ``__self__`` is set to ``None`` (but see the\n next item); ``__module__`` is the name of the module the\n function was defined in or ``None`` if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n ``alist.append()``, assuming *alist* is a list object. In this\n case, the special read-only attribute ``__self__`` is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override ``__new__()``. The arguments of the\n call are passed to ``__new__()`` and, in the typical case, to\n ``__init__()`` to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a ``__call__()`` method in their class.\n\nModules\n Modules are imported by the ``import`` statement (see section *The\n import statement*). A module object has a namespace implemented by\n a dictionary object (this is the dictionary referenced by the\n __globals__ attribute of functions defined in the module).\n Attribute references are translated to lookups in this dictionary,\n e.g., ``m.x`` is equivalent to ``m.__dict__["x"]``. A module object\n does not contain the code object used to initialize the module\n (since it isn\'t needed once the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., ``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``.\n\n Special read-only attribute: ``__dict__`` is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: ``__name__`` is the module\'s\n name; ``__doc__`` is the module\'s documentation string, or ``None``\n if unavailable; ``__file__`` is the pathname of the file from which\n the module was loaded, if it was loaded from a file. The\n ``__file__`` attribute is not present for C modules that are\n statically linked into the interpreter; for extension modules\n loaded dynamically from a shared library, it is the pathname of the\n shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., ``C.x`` is translated to\n ``C.__dict__["x"]`` (although there are a number of hooks which\n allow for other means of locating attributes). When the attribute\n name is not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n http://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class ``C``, say) would yield\n a class method object, it is transformed into an instance method\n object whose ``__self__`` attributes is ``C``. When it would yield\n a static method object, it is transformed into the object wrapped\n by the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its ``__dict__``.\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: ``__name__`` is the class name; ``__module__``\n is the module name in which the class was defined; ``__dict__`` is\n the dictionary containing the class\'s namespace; ``__bases__`` is a\n tuple (possibly empty or a singleton) containing the base classes,\n in the order of their occurrence in the base class list;\n ``__doc__`` is the class\'s documentation string, or None if\n undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose ``__self__`` attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s\n ``__dict__``. If no class attribute is found, and the object\'s\n class has a ``__getattr__()`` method, that is called to satisfy the\n lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n ``__setattr__()`` or ``__delattr__()`` method, this is called\n instead of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: ``__dict__`` is the attribute dictionary;\n ``__class__`` is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the ``open()`` built-in function,\n and also ``os.popen()``, ``os.fdopen()``, and the ``makefile()``\n method of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects ``sys.stdin``, ``sys.stdout`` and ``sys.stderr`` are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n ``io.TextIOBase`` abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: ``co_name`` gives the function\n name; ``co_argcount`` is the number of positional arguments\n (including arguments with default values); ``co_nlocals`` is the\n number of local variables used by the function (including\n arguments); ``co_varnames`` is a tuple containing the names of\n the local variables (starting with the argument names);\n ``co_cellvars`` is a tuple containing the names of local\n variables that are referenced by nested functions;\n ``co_freevars`` is a tuple containing the names of free\n variables; ``co_code`` is a string representing the sequence of\n bytecode instructions; ``co_consts`` is a tuple containing the\n literals used by the bytecode; ``co_names`` is a tuple\n containing the names used by the bytecode; ``co_filename`` is\n the filename from which the code was compiled;\n ``co_firstlineno`` is the first line number of the function;\n ``co_lnotab`` is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); ``co_stacksize`` is the required stack size\n (including local variables); ``co_flags`` is an integer encoding\n a number of flags for the interpreter.\n\n The following flag bits are defined for ``co_flags``: bit\n ``0x04`` is set if the function uses the ``*arguments`` syntax\n to accept an arbitrary number of positional arguments; bit\n ``0x08`` is set if the function uses the ``**keywords`` syntax\n to accept arbitrary keyword arguments; bit ``0x20`` is set if\n the function is a generator.\n\n Future feature declarations (``from __future__ import\n division``) also use bits in ``co_flags`` to indicate whether a\n code object was compiled with a particular feature enabled: bit\n ``0x2000`` is set if the function was compiled with future\n division enabled; bits ``0x10`` and ``0x1000`` were used in\n earlier versions of Python.\n\n Other bits in ``co_flags`` are reserved for internal use.\n\n If a code object represents a function, the first item in\n ``co_consts`` is the documentation string of the function, or\n ``None`` if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: ``f_back`` is to the previous\n stack frame (towards the caller), or ``None`` if this is the\n bottom stack frame; ``f_code`` is the code object being executed\n in this frame; ``f_locals`` is the dictionary used to look up\n local variables; ``f_globals`` is used for global variables;\n ``f_builtins`` is used for built-in (intrinsic) names;\n ``f_lasti`` gives the precise instruction (this is an index into\n the bytecode string of the code object).\n\n Special writable attributes: ``f_trace``, if not ``None``, is a\n function called at the start of each source code line (this is\n used by the debugger); ``f_lineno`` is the current line number\n of the frame --- writing to this from within a trace function\n jumps to the given line (only for the bottom-most frame). A\n debugger can implement a Jump command (aka Set Next Statement)\n by writing to f_lineno.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as the third item of the\n tuple returned by ``sys.exc_info()``. When the program contains\n no suitable handler, the stack trace is written (nicely\n formatted) to the standard error stream; if the interpreter is\n interactive, it is also made available to the user as\n ``sys.last_traceback``.\n\n Special read-only attributes: ``tb_next`` is the next level in\n the stack trace (towards the frame where the exception\n occurred), or ``None`` if there is no next level; ``tb_frame``\n points to the execution frame of the current level;\n ``tb_lineno`` gives the line number where the exception\n occurred; ``tb_lasti`` indicates the precise instruction. The\n line number and last instruction in the traceback may differ\n from the line number of its frame object if the exception\n occurred in a ``try`` statement with no matching except clause\n or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices for ``__getitem__()``\n methods. They are also created by the built-in ``slice()``\n function.\n\n Special read-only attributes: ``start`` is the lower bound;\n ``stop`` is the upper bound; ``step`` is the step value; each is\n ``None`` if omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n ``staticmethod()`` constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in ``classmethod()`` constructor.\n', 'typesfunctions': '\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: ``func(argument-list)``.\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', - 'typesmapping': '\nMapping Types --- ``dict``\n**************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built\nin ``list``, ``set``, and ``tuple`` classes, and the ``collections``\nmodule.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as ``1`` and ``1.0``) then they can be used interchangeably to\nindex the same dictionary entry. (Note however, that since computers\nstore floating-point numbers as approximations it is usually unwise to\nuse them as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of\n``key: value`` pairs within braces, for example: ``{\'jack\': 4098,\n\'sjoerd\': 4127}`` or ``{4098: \'jack\', 4127: \'sjoerd\'}``, or by the\n``dict`` constructor.\n\nclass class dict([arg])\n\n Return a new dictionary initialized from an optional positional\n argument or from a set of keyword arguments. If no arguments are\n given, return a new empty dictionary. If the positional argument\n *arg* is a mapping object, return a dictionary mapping the same\n keys to the same values as does the mapping object. Otherwise the\n positional argument must be a sequence, a container that supports\n iteration, or an iterator object. The elements of the argument\n must each also be of one of those kinds, and each must in turn\n contain exactly two objects. The first is used as a key in the new\n dictionary, and the second as the key\'s value. If a given key is\n seen more than once, the last value associated with it is retained\n in the new dictionary.\n\n If keyword arguments are given, the keywords themselves with their\n associated values are added as items to the dictionary. If a key\n is specified both in the positional argument and as a keyword\n argument, the value associated with the keyword is retained in the\n dictionary. For example, these all return a dictionary equal to\n ``{"one": 1, "two": 2}``:\n\n * ``dict(one=1, two=2)``\n\n * ``dict({\'one\': 1, \'two\': 2})``\n\n * ``dict(zip((\'one\', \'two\'), (1, 2)))``\n\n * ``dict([[\'two\', 2], [\'one\', 1]])``\n\n The first example only works for keys that are valid Python\n identifiers; the others work with any valid keys.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a ``KeyError`` if\n *key* is not in the map.\n\n If a subclass of dict defines a method ``__missing__()``, if the\n key *key* is not present, the ``d[key]`` operation calls that\n method with the key *key* as argument. The ``d[key]`` operation\n then returns or raises whatever is returned or raised by the\n ``__missing__(key)`` call if the key is not present. No other\n operations or methods invoke ``__missing__()``. If\n ``__missing__()`` is not defined, ``KeyError`` is raised.\n ``__missing__()`` must be a method; it cannot be an instance\n variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n See ``collections.Counter`` for a complete implementation\n including other methods helpful for accumulating and managing\n tallies.\n\n d[key] = value\n\n Set ``d[key]`` to *value*.\n\n del d[key]\n\n Remove ``d[key]`` from *d*. Raises a ``KeyError`` if *key* is\n not in the map.\n\n key in d\n\n Return ``True`` if *d* has a key *key*, else ``False``.\n\n key not in d\n\n Equivalent to ``not key in d``.\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for ``iter(d.keys())``.\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n ``fromkeys()`` is a class method that returns a new dictionary.\n *value* defaults to ``None``.\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to ``None``,\n so that this method never raises a ``KeyError``.\n\n items()\n\n Return a new view of the dictionary\'s items (``(key, value)``\n pairs). See below for documentation of view objects.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See below for\n documentation of view objects.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a ``KeyError`` is raised.\n\n popitem()\n\n Remove and return an arbitrary ``(key, value)`` pair from the\n dictionary.\n\n ``popitem()`` is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling ``popitem()`` raises a ``KeyError``.\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to ``None``.\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return ``None``.\n\n ``update()`` accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: ``d.update(red=1,\n blue=2)``.\n\n values()\n\n Return a new view of the dictionary\'s values. See below for\n documentation of view objects.\n\n\nDictionary view objects\n=======================\n\nThe objects returned by ``dict.keys()``, ``dict.values()`` and\n``dict.items()`` are *view objects*. They provide a dynamic view on\nthe dictionary\'s entries, which means that when the dictionary\nchanges, the view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of ``(key, value)``) in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of ``(value, key)`` pairs\n using ``zip()``: ``pairs = zip(d.values(), d.keys())``. Another\n way to create the same list is ``pairs = [(v, k) for (k, v) in\n d.items()]``.\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a ``RuntimeError`` or fail to iterate over all entries.\n\nx in dictview\n\n Return ``True`` if *x* is in the underlying dictionary\'s keys,\n values or items (in the latter case, *x* should be a ``(key,\n value)`` tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that ``(key, value)`` pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class ``collections.Set`` are available (for example, ``==``,\n``<``, or ``^``).\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', + 'typesmapping': '\nMapping Types --- ``dict``\n**************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built\nin ``list``, ``set``, and ``tuple`` classes, and the ``collections``\nmodule.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as ``1`` and ``1.0``) then they can be used interchangeably to\nindex the same dictionary entry. (Note however, that since computers\nstore floating-point numbers as approximations it is usually unwise to\nuse them as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of\n``key: value`` pairs within braces, for example: ``{\'jack\': 4098,\n\'sjoerd\': 4127}`` or ``{4098: \'jack\', 4127: \'sjoerd\'}``, or by the\n``dict`` constructor.\n\nclass class dict([arg])\n\n Return a new dictionary initialized from an optional positional\n argument or from a set of keyword arguments. If no arguments are\n given, return a new empty dictionary. If the positional argument\n *arg* is a mapping object, return a dictionary mapping the same\n keys to the same values as does the mapping object. Otherwise the\n positional argument must be a sequence, a container that supports\n iteration, or an iterator object. The elements of the argument\n must each also be of one of those kinds, and each must in turn\n contain exactly two objects. The first is used as a key in the new\n dictionary, and the second as the key\'s value. If a given key is\n seen more than once, the last value associated with it is retained\n in the new dictionary.\n\n If keyword arguments are given, the keywords themselves with their\n associated values are added as items to the dictionary. If a key\n is specified both in the positional argument and as a keyword\n argument, the value associated with the keyword is retained in the\n dictionary. For example, these all return a dictionary equal to\n ``{"one": 1, "two": 2}``:\n\n * ``dict(one=1, two=2)``\n\n * ``dict({\'one\': 1, \'two\': 2})``\n\n * ``dict(zip((\'one\', \'two\'), (1, 2)))``\n\n * ``dict([[\'two\', 2], [\'one\', 1]])``\n\n The first example only works for keys that are valid Python\n identifiers; the others work with any valid keys.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a ``KeyError`` if\n *key* is not in the map.\n\n If a subclass of dict defines a method ``__missing__()``, if the\n key *key* is not present, the ``d[key]`` operation calls that\n method with the key *key* as argument. The ``d[key]`` operation\n then returns or raises whatever is returned or raised by the\n ``__missing__(key)`` call if the key is not present. No other\n operations or methods invoke ``__missing__()``. If\n ``__missing__()`` is not defined, ``KeyError`` is raised.\n ``__missing__()`` must be a method; it cannot be an instance\n variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n See ``collections.Counter`` for a complete implementation\n including other methods helpful for accumulating and managing\n tallies.\n\n Changed in version 3.3: If the dict is modified during the\n lookup, a ``RuntimeError`` exception is now raised.\n\n d[key] = value\n\n Set ``d[key]`` to *value*.\n\n del d[key]\n\n Remove ``d[key]`` from *d*. Raises a ``KeyError`` if *key* is\n not in the map.\n\n key in d\n\n Return ``True`` if *d* has a key *key*, else ``False``.\n\n key not in d\n\n Equivalent to ``not key in d``.\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for ``iter(d.keys())``.\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n ``fromkeys()`` is a class method that returns a new dictionary.\n *value* defaults to ``None``.\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to ``None``,\n so that this method never raises a ``KeyError``.\n\n items()\n\n Return a new view of the dictionary\'s items (``(key, value)``\n pairs). See below for documentation of view objects.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See below for\n documentation of view objects.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a ``KeyError`` is raised.\n\n popitem()\n\n Remove and return an arbitrary ``(key, value)`` pair from the\n dictionary.\n\n ``popitem()`` is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling ``popitem()`` raises a ``KeyError``.\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to ``None``.\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return ``None``.\n\n ``update()`` accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: ``d.update(red=1,\n blue=2)``.\n\n values()\n\n Return a new view of the dictionary\'s values. See below for\n documentation of view objects.\n\n\nDictionary view objects\n=======================\n\nThe objects returned by ``dict.keys()``, ``dict.values()`` and\n``dict.items()`` are *view objects*. They provide a dynamic view on\nthe dictionary\'s entries, which means that when the dictionary\nchanges, the view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of ``(key, value)``) in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of ``(value, key)`` pairs\n using ``zip()``: ``pairs = zip(d.values(), d.keys())``. Another\n way to create the same list is ``pairs = [(v, k) for (k, v) in\n d.items()]``.\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a ``RuntimeError`` or fail to iterate over all entries.\n\nx in dictview\n\n Return ``True`` if *x* is in the underlying dictionary\'s keys,\n values or items (in the latter case, *x* should be a ``(key,\n value)`` tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that ``(key, value)`` pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class ``collections.Set`` are available (for example, ``==``,\n``<``, or ``^``).\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', 'typesmethods': "\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as ``append()`` on\nlists) and class instance methods. Built-in methods are described\nwith the types that support them.\n\nIf you access a method (a function defined in a class namespace)\nthrough an instance, you get a special object: a *bound method* (also\ncalled *instance method*) object. When called, it will add the\n``self`` argument to the argument list. Bound methods have two\nspecial read-only attributes: ``m.__self__`` is the object on which\nthe method operates, and ``m.__func__`` is the function implementing\nthe method. Calling ``m(arg-1, arg-2, ..., arg-n)`` is completely\nequivalent to calling ``m.__func__(m.__self__, arg-1, arg-2, ...,\narg-n)``.\n\nLike function objects, bound method objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object (``meth.__func__``), setting method\nattributes on bound methods is disallowed. Attempting to set a method\nattribute results in a ``TypeError`` being raised. In order to set a\nmethod attribute, you need to explicitly set it on the underlying\nfunction object:\n\n class C:\n def method(self):\n pass\n\n c = C()\n c.method.__func__.whoami = 'my name is c'\n\nSee *The standard type hierarchy* for more information.\n", 'typesmodules': "\nModules\n*******\n\nThe only special operation on a module is attribute access:\n``m.name``, where *m* is a module and *name* accesses a name defined\nin *m*'s symbol table. Module attributes can be assigned to. (Note\nthat the ``import`` statement is not, strictly speaking, an operation\non a module object; ``import foo`` does not require a module object\nnamed *foo* to exist, rather it requires an (external) *definition*\nfor a module named *foo* somewhere.)\n\nA special attribute of every module is ``__dict__``. This is the\ndictionary containing the module's symbol table. Modifying this\ndictionary will actually change the module's symbol table, but direct\nassignment to the ``__dict__`` attribute is not possible (you can\nwrite ``m.__dict__['a'] = 1``, which defines ``m.a`` to be ``1``, but\nyou can't write ``m.__dict__ = {}``). Modifying ``__dict__`` directly\nis not recommended.\n\nModules built into the interpreter are written like this: ````. If loaded from a file, they are written as\n````.\n", - 'typesseq': '\nSequence Types --- ``str``, ``bytes``, ``bytearray``, ``list``, ``tuple``, ``range``\n************************************************************************************\n\nThere are six sequence types: strings, byte sequences (``bytes``\nobjects), byte arrays (``bytearray`` objects), lists, tuples, and\nrange objects. For other containers see the built in ``dict`` and\n``set`` classes, and the ``collections`` module.\n\nStrings contain Unicode characters. Their literals are written in\nsingle or double quotes: ``\'xyzzy\'``, ``"frobozz"``. See *String and\nBytes literals* for more about string literals. In addition to the\nfunctionality described here, there are also string-specific methods\ndescribed in the *String Methods* section.\n\nBytes and bytearray objects contain single bytes -- the former is\nimmutable while the latter is a mutable sequence. Bytes objects can\nbe constructed the constructor, ``bytes()``, and from literals; use a\n``b`` prefix with normal string syntax: ``b\'xyzzy\'``. To construct\nbyte arrays, use the ``bytearray()`` function.\n\nWhile string objects are sequences of characters (represented by\nstrings of length 1), bytes and bytearray objects are sequences of\n*integers* (between 0 and 255), representing the ASCII value of single\nbytes. That means that for a bytes or bytearray object *b*, ``b[0]``\nwill be an integer, while ``b[0:1]`` will be a bytes or bytearray\nobject of length 1. The representation of bytes objects uses the\nliteral format (``b\'...\'``) since it is generally more useful than\ne.g. ``bytes([50, 19, 100])``. You can always convert a bytes object\ninto a list of integers using ``list(b)``.\n\nAlso, while in previous Python versions, byte strings and Unicode\nstrings could be exchanged for each other rather freely (barring\nencoding issues), strings and bytes are now completely separate\nconcepts. There\'s no implicit en-/decoding if you pass an object of\nthe wrong type. A string always compares unequal to a bytes or\nbytearray object.\n\nLists are constructed with square brackets, separating items with\ncommas: ``[a, b, c]``. Tuples are constructed by the comma operator\n(not within square brackets), with or without enclosing parentheses,\nbut an empty tuple must have the enclosing parentheses, such as ``a,\nb, c`` or ``()``. A single item tuple must have a trailing comma,\nsuch as ``(d,)``.\n\nObjects of type range are created using the ``range()`` function.\nThey don\'t support concatenation or repetition, and using ``min()`` or\n``max()`` on them is inefficient.\n\nMost sequence types support the following operations. The ``in`` and\n``not in`` operations have the same priorities as the comparison\noperations. The ``+`` and ``*`` operations have the same priority as\nthe corresponding numeric operations. [3] Additional methods are\nprovided for *Mutable Sequence Types*.\n\nThis table lists the sequence operations sorted in ascending priority\n(operations in the same box have the same priority). In the table,\n*s* and *t* are sequences of the same type; *n*, *i*, *j* and *k* are\nintegers.\n\n+--------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+====================+==================================+============+\n| ``x in s`` | ``True`` if an item of *s* is | (1) |\n| | equal to *x*, else ``False`` | |\n+--------------------+----------------------------------+------------+\n| ``x not in s`` | ``False`` if an item of *s* is | (1) |\n| | equal to *x*, else ``True`` | |\n+--------------------+----------------------------------+------------+\n| ``s + t`` | the concatenation of *s* and *t* | (6) |\n+--------------------+----------------------------------+------------+\n| ``s * n, n * s`` | *n* shallow copies of *s* | (2) |\n| | concatenated | |\n+--------------------+----------------------------------+------------+\n| ``s[i]`` | *i*th item of *s*, origin 0 | (3) |\n+--------------------+----------------------------------+------------+\n| ``s[i:j]`` | slice of *s* from *i* to *j* | (3)(4) |\n+--------------------+----------------------------------+------------+\n| ``s[i:j:k]`` | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+--------------------+----------------------------------+------------+\n| ``len(s)`` | length of *s* | |\n+--------------------+----------------------------------+------------+\n| ``min(s)`` | smallest item of *s* | |\n+--------------------+----------------------------------+------------+\n| ``max(s)`` | largest item of *s* | |\n+--------------------+----------------------------------+------------+\n| ``s.index(i)`` | index of the first occurence of | |\n| | *i* in *s* | |\n+--------------------+----------------------------------+------------+\n| ``s.count(i)`` | total number of occurences of | |\n| | *i* in *s* | |\n+--------------------+----------------------------------+------------+\n\nSequence types also support comparisons. In particular, tuples and\nlists are compared lexicographically by comparing corresponding\nelements. This means that to compare equal, every element must\ncompare equal and the two sequences must be of the same type and have\nthe same length. (For full details see *Comparisons* in the language\nreference.)\n\nNotes:\n\n1. When *s* is a string object, the ``in`` and ``not in`` operations\n act like a substring test.\n\n2. Values of *n* less than ``0`` are treated as ``0`` (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that ``[[]]`` is a one-element list containing\n an empty list, so all three elements of ``[[]] * 3`` are (pointers\n to) this single empty list. Modifying any of the elements of\n ``lists`` modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of the\n string: ``len(s) + i`` or ``len(s) + j`` is substituted. But note\n that ``-0`` is still ``0``.\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that ``i <= k < j``. If *i* or *j* is\n greater than ``len(s)``, use ``len(s)``. If *i* is omitted or\n ``None``, use ``0``. If *j* is omitted or ``None``, use\n ``len(s)``. If *i* is greater than or equal to *j*, the slice is\n empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index ``x = i + n*k`` such that ``0 <= n <\n (j-i)/k``. In other words, the indices are ``i``, ``i+k``,\n ``i+2*k``, ``i+3*k`` and so on, stopping when *j* is reached (but\n never including *j*). If *i* or *j* is greater than ``len(s)``,\n use ``len(s)``. If *i* or *j* are omitted or ``None``, they become\n "end" values (which end depends on the sign of *k*). Note, *k*\n cannot be zero. If *k* is ``None``, it is treated like ``1``.\n\n6. Concatenating immutable strings always results in a new object.\n This means that building up a string by repeated concatenation will\n have a quadratic runtime cost in the total string length. To get a\n linear runtime cost, you must switch to one of the alternatives\n below:\n\n * if concatenating ``str`` objects, you can build a list and use\n ``str.join()`` at the end;\n\n * if concatenating ``bytes`` objects, you can similarly use\n ``bytes.join()``, or you can do in-place concatenation with a\n ``bytearray`` object. ``bytearray`` objects are mutable and have\n an efficient overallocation mechanism.\n\n\nString Methods\n==============\n\nString objects support the methods listed below.\n\nIn addition, Python\'s strings support the sequence type methods\ndescribed in the *Sequence Types --- str, bytes, bytearray, list,\ntuple, range* section. To output formatted strings, see the *String\nFormatting* section. Also, see the ``re`` module for string functions\nbased on regular expressions.\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 ``\'\xc3\x9f\'`` is equivalent to\n ``"ss"``. Since it is already lowercase, ``lower()`` would do\n nothing to ``\'\xc3\x9f\'``; ``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 a space).\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\n possible values are ``\'ignore\'``, ``\'replace\'``,\n ``\'xmlcharrefreplace\'``, ``\'backslashreplace\'`` and any other name\n registered via ``codecs.register_error()``, see section *Codec Base\n Classes*. For a list of possible encodings, see section *Standard\n 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\n suffixes to look for. With optional *start*, test beginning at\n that position. With optional *end*, stop comparing at that\n position.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by zero or more spaces, depending on the current column and the\n given tab size. The column number is reset to zero after each\n newline occurring in the string. If *tabsize* is not given, a tab\n size of ``8`` characters is assumed. This doesn\'t understand other\n non-printing characters or escape sequences.\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 the\n position of *sub*. To check if *sub* is a substring or not, use\n 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\n used directly and not copied to a ``dict`` . This is useful if for\n example ``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\n ``c`` is alphanumeric if one of the following returns ``True``:\n ``c.isalpha()``, ``c.isdecimal()``, ``c.isdigit()``, or\n ``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\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 a\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*\n is 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 a\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\n splitting from the right, ``rsplit()`` behaves like ``split()``\n which is 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, then there is no limit\n 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*\n argument may consist of multiple characters (for example,\n ``\'1<>2<>3\'.split(\'<>\')`` returns ``[\'1\', \'2\', \'3\']``). Splitting\n an empty string with a specified separator returns ``[\'\']``.\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\n For example, ``\' 1 2 3 \'.split()`` returns ``[\'1\', \'2\', \'3\']``,\n and ``\' 1 2 3 \'.split(None, 1)`` returns ``[\'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\nstr.startswith(prefix[, start[, end]])\n\n Return ``True`` if string starts with the *prefix*, otherwise\n return ``False``. *prefix* can also be a tuple of prefixes to look\n for. With optional *start*, test string beginning at that\n position. With optional *end*, stop comparing string at that\n 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\n *chars* argument defaults to removing whitespace. The *chars*\n argument is not a prefix or suffix; rather, all combinations of its\n values are stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\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 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 character\n 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\n be ``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 the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to ``len(s)``.\n\n\nOld String Formatting Operations\n================================\n\nNote: The formatting operations described here are modelled on C\'s\n printf() syntax. They only support formatting of certain builtin\n types. The use of a binary operator means that care may be needed\n in order to format tuples and dictionaries correctly. As the new\n *String Formatting* syntax is more flexible and handles tuples and\n dictionaries naturally, it is recommended for new code. However,\n there are no current plans to deprecate printf-style formatting.\n\nString objects have one unique built-in operation: the ``%`` operator\n(modulo). This is also known as the string *formatting* or\n*interpolation* operator. Given ``format % values`` (where *format* is\na string), ``%`` conversion specifications in *format* are replaced\nwith zero or more elements of *values*. The effect is similar to the\nusing ``sprintf()`` in the C language.\n\nIf *format* requires a single argument, *values* may be a single non-\ntuple object. [5] Otherwise, *values* must be a tuple with exactly\nthe number of items specified by the format string, or a single\nmapping object (for example, a dictionary).\n\nA conversion specifier contains two or more characters and has the\nfollowing components, which must occur in this order:\n\n1. The ``\'%\'`` character, which marks the start of the specifier.\n\n2. Mapping key (optional), consisting of a parenthesised sequence of\n characters (for example, ``(somename)``).\n\n3. Conversion flags (optional), which affect the result of some\n conversion types.\n\n4. Minimum field width (optional). If specified as an ``\'*\'``\n (asterisk), the actual width is read from the next element of the\n tuple in *values*, and the object to convert comes after the\n minimum field width and optional precision.\n\n5. Precision (optional), given as a ``\'.\'`` (dot) followed by the\n precision. If specified as ``\'*\'`` (an asterisk), the actual\n precision is read from the next element of the tuple in *values*,\n and the value to convert comes after the precision.\n\n6. Length modifier (optional).\n\n7. Conversion type.\n\nWhen the right argument is a dictionary (or other mapping type), then\nthe formats in the string *must* include a parenthesised mapping key\ninto that dictionary inserted immediately after the ``\'%\'`` character.\nThe mapping key selects the value to be formatted from the mapping.\nFor example:\n\n>>> print(\'%(language)s has %(number)03d quote types.\' %\n... {\'language\': "Python", "number": 2})\nPython has 002 quote types.\n\nIn this case no ``*`` specifiers may occur in a format (since they\nrequire a sequential parameter list).\n\nThe conversion flag characters are:\n\n+-----------+-----------------------------------------------------------------------+\n| Flag | Meaning |\n+===========+=======================================================================+\n| ``\'#\'`` | The value conversion will use the "alternate form" (where defined |\n| | below). |\n+-----------+-----------------------------------------------------------------------+\n| ``\'0\'`` | The conversion will be zero padded for numeric values. |\n+-----------+-----------------------------------------------------------------------+\n| ``\'-\'`` | The converted value is left adjusted (overrides the ``\'0\'`` |\n| | conversion if both are given). |\n+-----------+-----------------------------------------------------------------------+\n| ``\' \'`` | (a space) A blank should be left before a positive number (or empty |\n| | string) produced by a signed conversion. |\n+-----------+-----------------------------------------------------------------------+\n| ``\'+\'`` | A sign character (``\'+\'`` or ``\'-\'``) will precede the conversion |\n| | (overrides a "space" flag). |\n+-----------+-----------------------------------------------------------------------+\n\nA length modifier (``h``, ``l``, or ``L``) may be present, but is\nignored as it is not necessary for Python -- so e.g. ``%ld`` is\nidentical to ``%d``.\n\nThe conversion types are:\n\n+--------------+-------------------------------------------------------+---------+\n| Conversion | Meaning | Notes |\n+==============+=======================================================+=========+\n| ``\'d\'`` | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'i\'`` | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'o\'`` | Signed octal value. | (1) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'u\'`` | Obsolete type -- it is identical to ``\'d\'``. | (7) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'x\'`` | Signed hexadecimal (lowercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'X\'`` | Signed hexadecimal (uppercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'e\'`` | Floating point exponential format (lowercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'E\'`` | Floating point exponential format (uppercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'f\'`` | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'F\'`` | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'g\'`` | Floating point format. Uses lowercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'G\'`` | Floating point format. Uses uppercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'c\'`` | Single character (accepts integer or single character | |\n| | string). | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'r\'`` | String (converts any Python object using ``repr()``). | (5) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'s\'`` | String (converts any Python object using ``str()``). | (5) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'a\'`` | String (converts any Python object using | (5) |\n| | ``ascii()``). | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'%\'`` | No argument is converted, results in a ``\'%\'`` | |\n| | character in the result. | |\n+--------------+-------------------------------------------------------+---------+\n\nNotes:\n\n1. The alternate form causes a leading zero (``\'0\'``) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n2. The alternate form causes a leading ``\'0x\'`` or ``\'0X\'`` (depending\n on whether the ``\'x\'`` or ``\'X\'`` format was used) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n3. The alternate form causes the result to always contain a decimal\n point, even if no digits follow it.\n\n The precision determines the number of digits after the decimal\n point and defaults to 6.\n\n4. The alternate form causes the result to always contain a decimal\n point, and trailing zeroes are not removed as they would otherwise\n be.\n\n The precision determines the number of significant digits before\n and after the decimal point and defaults to 6.\n\n5. If precision is ``N``, the output is truncated to ``N`` characters.\n\n1. See **PEP 237**.\n\nSince Python strings have an explicit length, ``%s`` conversions do\nnot assume that ``\'\\0\'`` is the end of the string.\n\nChanged in version 3.1: ``%f`` conversions for numbers whose absolute\nvalue is over 1e50 are no longer replaced by ``%g`` conversions.\n\nAdditional string operations are defined in standard modules\n``string`` and ``re``.\n\n\nRange Type\n==========\n\nThe ``range`` type is an immutable sequence which is commonly used for\nlooping. The advantage of the ``range`` type is that an ``range``\nobject will always take the same amount of memory, no matter the size\nof the range it represents.\n\nRange objects have relatively little behavior: they support indexing,\ncontains, iteration, the ``len()`` function, and the following\nmethods:\n\nrange.count(x)\n\n Return the number of *i*\'s for which ``s[i] == x``.\n\n New in version 3.2.\n\nrange.index(x)\n\n Return the smallest *i* such that ``s[i] == x``. Raises\n ``ValueError`` when *x* is not in the range.\n\n New in version 3.2.\n\n\nMutable Sequence Types\n======================\n\nList and bytearray objects support additional operations that allow\nin-place modification of the object. Other mutable sequence types\n(when added to the language) should also support these operations.\nStrings and tuples are immutable sequence types: such objects cannot\nbe modified once created. The following operations are defined on\nmutable sequence types (where *x* is an arbitrary object).\n\nNote that while lists allow their items to be of any type, bytearray\nobject "items" are all integers in the range 0 <= x < 256.\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | same as ``s[len(s):len(s)] = | |\n| | [x]`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(x)`` | same as ``s[len(s):len(s)] = x`` | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.clear()`` | remove all items from ``s`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.copy()`` | return a shallow copy of ``s`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.count(x)`` | return number of *i*\'s for which | |\n| | ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.index(x[, i[, j]])`` | return smallest *k* such that | (3) |\n| | ``s[k] == x`` and ``i <= k < j`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | same as ``s[i:i] = [x]`` | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | same as ``x = s[i]; del s[i]; | (5) |\n| | return x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | same as ``del s[s.index(x)]`` | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (6) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.sort([key[, reverse]])`` | sort the items of *s* in place | (6), (7), (8) |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. *x* can be any iterable object.\n\n3. Raises ``ValueError`` when *x* is not found in *s*. When a negative\n index is passed as the second or third parameter to the ``index()``\n method, the sequence length is added, as for slice indices. If it\n is still negative, it is truncated to zero, as for slice indices.\n\n4. When a negative index is passed as the first parameter to the\n ``insert()`` method, the sequence length is added, as for slice\n indices. If it is still negative, it is truncated to zero, as for\n slice indices.\n\n5. The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n6. The ``sort()`` and ``reverse()`` methods modify the sequence in\n place for economy of space when sorting or reversing a large\n sequence. To remind you that they operate by side effect, they\n don\'t return the sorted or reversed sequence.\n\n7. The ``sort()`` method takes optional arguments for controlling the\n comparisons. Each must be specified as a keyword argument.\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: ``key=str.lower``. The\n default value is ``None``. Use ``functools.cmp_to_key()`` to\n convert an old-style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n The ``sort()`` method is guaranteed to be stable. A sort is stable\n if it guarantees not to change the relative order of elements that\n compare equal --- this is helpful for sorting in multiple passes\n (for example, sort by department, then by salary grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises ``ValueError`` if it can detect\n that the list has been mutated during a sort.\n\n8. ``sort()`` is not supported by ``bytearray`` objects.\n\n New in version 3.3: ``clear()`` and ``copy()`` methods.\n\n\nBytes and Byte Array Methods\n============================\n\nBytes and bytearray objects, being "strings of bytes", have all\nmethods found on strings, with the exception of ``encode()``,\n``format()`` and ``isidentifier()``, which do not make sense with\nthese types. For converting the objects to strings, they have a\n``decode()`` method.\n\nWherever one of these methods needs to interpret the bytes as\ncharacters (e.g. the ``is...()`` methods), the ASCII character set is\nassumed.\n\nNew in version 3.3: The functions ``count()``, ``find()``,\n``index()``, ``rfind()`` and ``rindex()`` have additional semantics\ncompared to the corresponding string functions: They also accept an\ninteger in range 0 to 255 (a byte) as their first argument.\n\nNote: The methods on bytes and bytearray objects don\'t accept strings as\n their arguments, just as the methods on strings don\'t accept bytes\n as their arguments. For example, you have to write\n\n a = "abc"\n b = a.replace("a", "f")\n\n and\n\n a = b"abc"\n b = a.replace(b"a", b"f")\n\nbytes.decode(encoding="utf-8", errors="strict")\nbytearray.decode(encoding="utf-8", errors="strict")\n\n Return a string decoded from the given bytes. Default encoding is\n ``\'utf-8\'``. *errors* may be given to set a different error\n handling scheme. The default for *errors* is ``\'strict\'``, meaning\n that encoding errors raise a ``UnicodeError``. Other possible\n values are ``\'ignore\'``, ``\'replace\'`` and any other name\n registered via ``codecs.register_error()``, see section *Codec Base\n Classes*. For a list of possible encodings, see section *Standard\n Encodings*.\n\n Changed in version 3.1: Added support for keyword arguments.\n\nThe bytes and bytearray types have an additional class method:\n\nclassmethod bytes.fromhex(string)\nclassmethod bytearray.fromhex(string)\n\n This ``bytes`` class method returns a bytes or bytearray object,\n decoding the given string object. The string must contain two\n hexadecimal digits per byte, spaces are ignored.\n\n >>> bytes.fromhex(\'f0 f1f2 \')\n b\'\\xf0\\xf1\\xf2\'\n\nThe maketrans and translate methods differ in semantics from the\nversions available on strings:\n\nbytes.translate(table[, delete])\nbytearray.translate(table[, delete])\n\n Return a copy of the bytes or bytearray object where all bytes\n occurring in the optional argument *delete* are removed, and the\n remaining bytes have been mapped through the given translation\n table, which must be a bytes object of length 256.\n\n You can use the ``bytes.maketrans()`` method to create a\n translation table.\n\n Set the *table* argument to ``None`` for translations that only\n delete characters:\n\n >>> b\'read this short text\'.translate(None, b\'aeiou\')\n b\'rd ths shrt txt\'\n\nstatic bytes.maketrans(from, to)\nstatic bytearray.maketrans(from, to)\n\n This static method returns a translation table usable for\n ``bytes.translate()`` that will map each character in *from* into\n the character at the same position in *to*; *from* and *to* must be\n bytes objects and have the same length.\n\n New in version 3.1.\n', + 'typesseq': '\nSequence Types --- ``str``, ``bytes``, ``bytearray``, ``list``, ``tuple``, ``range``\n************************************************************************************\n\nThere are six sequence types: strings, byte sequences (``bytes``\nobjects), byte arrays (``bytearray`` objects), lists, tuples, and\nrange objects. For other containers see the built in ``dict`` and\n``set`` classes, and the ``collections`` module.\n\nStrings contain Unicode characters. Their literals are written in\nsingle or double quotes: ``\'xyzzy\'``, ``"frobozz"``. See *String and\nBytes literals* for more about string literals. In addition to the\nfunctionality described here, there are also string-specific methods\ndescribed in the *String Methods* section.\n\nBytes and bytearray objects contain single bytes -- the former is\nimmutable while the latter is a mutable sequence. Bytes objects can\nbe constructed the constructor, ``bytes()``, and from literals; use a\n``b`` prefix with normal string syntax: ``b\'xyzzy\'``. To construct\nbyte arrays, use the ``bytearray()`` function.\n\nWhile string objects are sequences of characters (represented by\nstrings of length 1), bytes and bytearray objects are sequences of\n*integers* (between 0 and 255), representing the ASCII value of single\nbytes. That means that for a bytes or bytearray object *b*, ``b[0]``\nwill be an integer, while ``b[0:1]`` will be a bytes or bytearray\nobject of length 1. The representation of bytes objects uses the\nliteral format (``b\'...\'``) since it is generally more useful than\ne.g. ``bytes([50, 19, 100])``. You can always convert a bytes object\ninto a list of integers using ``list(b)``.\n\nAlso, while in previous Python versions, byte strings and Unicode\nstrings could be exchanged for each other rather freely (barring\nencoding issues), strings and bytes are now completely separate\nconcepts. There\'s no implicit en-/decoding if you pass an object of\nthe wrong type. A string always compares unequal to a bytes or\nbytearray object.\n\nLists are constructed with square brackets, separating items with\ncommas: ``[a, b, c]``. Tuples are constructed by the comma operator\n(not within square brackets), with or without enclosing parentheses,\nbut an empty tuple must have the enclosing parentheses, such as ``a,\nb, c`` or ``()``. A single item tuple must have a trailing comma,\nsuch as ``(d,)``.\n\nObjects of type range are created using the ``range()`` function.\nThey don\'t support concatenation or repetition, and using ``min()`` or\n``max()`` on them is inefficient.\n\nMost sequence types support the following operations. The ``in`` and\n``not in`` operations have the same priorities as the comparison\noperations. The ``+`` and ``*`` operations have the same priority as\nthe corresponding numeric operations. [3] Additional methods are\nprovided for *Mutable Sequence Types*.\n\nThis table lists the sequence operations sorted in ascending priority\n(operations in the same box have the same priority). In the table,\n*s* and *t* are sequences of the same type; *n*, *i*, *j* and *k* are\nintegers.\n\n+--------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+====================+==================================+============+\n| ``x in s`` | ``True`` if an item of *s* is | (1) |\n| | equal to *x*, else ``False`` | |\n+--------------------+----------------------------------+------------+\n| ``x not in s`` | ``False`` if an item of *s* is | (1) |\n| | equal to *x*, else ``True`` | |\n+--------------------+----------------------------------+------------+\n| ``s + t`` | the concatenation of *s* and *t* | (6) |\n+--------------------+----------------------------------+------------+\n| ``s * n, n * s`` | *n* shallow copies of *s* | (2) |\n| | concatenated | |\n+--------------------+----------------------------------+------------+\n| ``s[i]`` | *i*th item of *s*, origin 0 | (3) |\n+--------------------+----------------------------------+------------+\n| ``s[i:j]`` | slice of *s* from *i* to *j* | (3)(4) |\n+--------------------+----------------------------------+------------+\n| ``s[i:j:k]`` | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+--------------------+----------------------------------+------------+\n| ``len(s)`` | length of *s* | |\n+--------------------+----------------------------------+------------+\n| ``min(s)`` | smallest item of *s* | |\n+--------------------+----------------------------------+------------+\n| ``max(s)`` | largest item of *s* | |\n+--------------------+----------------------------------+------------+\n| ``s.index(i)`` | index of the first occurence of | |\n| | *i* in *s* | |\n+--------------------+----------------------------------+------------+\n| ``s.count(i)`` | total number of occurences of | |\n| | *i* in *s* | |\n+--------------------+----------------------------------+------------+\n\nSequence types also support comparisons. In particular, tuples and\nlists are compared lexicographically by comparing corresponding\nelements. This means that to compare equal, every element must\ncompare equal and the two sequences must be of the same type and have\nthe same length. (For full details see *Comparisons* in the language\nreference.)\n\nNotes:\n\n1. When *s* is a string object, the ``in`` and ``not in`` operations\n act like a substring test.\n\n2. Values of *n* less than ``0`` are treated as ``0`` (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that ``[[]]`` is a one-element list containing\n an empty list, so all three elements of ``[[]] * 3`` are (pointers\n to) this single empty list. Modifying any of the elements of\n ``lists`` modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of the\n string: ``len(s) + i`` or ``len(s) + j`` is substituted. But note\n that ``-0`` is still ``0``.\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that ``i <= k < j``. If *i* or *j* is\n greater than ``len(s)``, use ``len(s)``. If *i* is omitted or\n ``None``, use ``0``. If *j* is omitted or ``None``, use\n ``len(s)``. If *i* is greater than or equal to *j*, the slice is\n empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index ``x = i + n*k`` such that ``0 <= n <\n (j-i)/k``. In other words, the indices are ``i``, ``i+k``,\n ``i+2*k``, ``i+3*k`` and so on, stopping when *j* is reached (but\n never including *j*). If *i* or *j* is greater than ``len(s)``,\n use ``len(s)``. If *i* or *j* are omitted or ``None``, they become\n "end" values (which end depends on the sign of *k*). Note, *k*\n cannot be zero. If *k* is ``None``, it is treated like ``1``.\n\n6. Concatenating immutable strings always results in a new object.\n This means that building up a string by repeated concatenation will\n have a quadratic runtime cost in the total string length. To get a\n linear runtime cost, you must switch to one of the alternatives\n below:\n\n * if concatenating ``str`` objects, you can build a list and use\n ``str.join()`` at the end;\n\n * if concatenating ``bytes`` objects, you can similarly use\n ``bytes.join()``, or you can do in-place concatenation with a\n ``bytearray`` object. ``bytearray`` objects are mutable and have\n an efficient overallocation mechanism.\n\n\nString Methods\n==============\n\nString objects support the methods listed below.\n\nIn addition, Python\'s strings support the sequence type methods\ndescribed in the *Sequence Types --- str, bytes, bytearray, list,\ntuple, range* section. To output formatted strings, see the *String\nFormatting* section. Also, see the ``re`` module for string functions\nbased on regular expressions.\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 ``\'\xc3\x9f\'`` is equivalent to\n ``"ss"``. Since it is already lowercase, ``lower()`` would do\n nothing to ``\'\xc3\x9f\'``; ``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 a space).\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\n possible values are ``\'ignore\'``, ``\'replace\'``,\n ``\'xmlcharrefreplace\'``, ``\'backslashreplace\'`` and any other name\n registered via ``codecs.register_error()``, see section *Codec Base\n Classes*. For a list of possible encodings, see section *Standard\n 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\n suffixes to look for. With optional *start*, test beginning at\n that position. With optional *end*, stop comparing at that\n position.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by zero or more spaces, depending on the current column and the\n given tab size. The column number is reset to zero after each\n newline occurring in the string. If *tabsize* is not given, a tab\n size of ``8`` characters is assumed. This doesn\'t understand other\n non-printing characters or escape sequences.\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 the\n position of *sub*. To check if *sub* is a substring or not, use\n 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\n used directly and not copied to a ``dict`` . This is useful if for\n example ``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\n ``c`` is alphanumeric if one of the following returns ``True``:\n ``c.isalpha()``, ``c.isdecimal()``, ``c.isdigit()``, or\n ``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\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 a\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*\n is 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 a\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\n splitting from the right, ``rsplit()`` behaves like ``split()``\n which is 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, then there is no limit\n 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*\n argument may consist of multiple characters (for example,\n ``\'1<>2<>3\'.split(\'<>\')`` returns ``[\'1\', \'2\', \'3\']``). Splitting\n an empty string with a specified separator returns ``[\'\']``.\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\n For example, ``\' 1 2 3 \'.split()`` returns ``[\'1\', \'2\', \'3\']``,\n and ``\' 1 2 3 \'.split(None, 1)`` returns ``[\'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\nstr.startswith(prefix[, start[, end]])\n\n Return ``True`` if string starts with the *prefix*, otherwise\n return ``False``. *prefix* can also be a tuple of prefixes to look\n for. With optional *start*, test string beginning at that\n position. With optional *end*, stop comparing string at that\n 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\n *chars* argument defaults to removing whitespace. The *chars*\n argument is not a prefix or suffix; rather, all combinations of its\n values are stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\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 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 character\n 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\n be ``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 the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to ``len(s)``.\n\n\nOld String Formatting Operations\n================================\n\nNote: The formatting operations described here are modelled on C\'s\n printf() syntax. They only support formatting of certain builtin\n types. The use of a binary operator means that care may be needed\n in order to format tuples and dictionaries correctly. As the new\n *String Formatting* syntax is more flexible and handles tuples and\n dictionaries naturally, it is recommended for new code. However,\n there are no current plans to deprecate printf-style formatting.\n\nString objects have one unique built-in operation: the ``%`` operator\n(modulo). This is also known as the string *formatting* or\n*interpolation* operator. Given ``format % values`` (where *format* is\na string), ``%`` conversion specifications in *format* are replaced\nwith zero or more elements of *values*. The effect is similar to the\nusing ``sprintf()`` in the C language.\n\nIf *format* requires a single argument, *values* may be a single non-\ntuple object. [5] Otherwise, *values* must be a tuple with exactly\nthe number of items specified by the format string, or a single\nmapping object (for example, a dictionary).\n\nA conversion specifier contains two or more characters and has the\nfollowing components, which must occur in this order:\n\n1. The ``\'%\'`` character, which marks the start of the specifier.\n\n2. Mapping key (optional), consisting of a parenthesised sequence of\n characters (for example, ``(somename)``).\n\n3. Conversion flags (optional), which affect the result of some\n conversion types.\n\n4. Minimum field width (optional). If specified as an ``\'*\'``\n (asterisk), the actual width is read from the next element of the\n tuple in *values*, and the object to convert comes after the\n minimum field width and optional precision.\n\n5. Precision (optional), given as a ``\'.\'`` (dot) followed by the\n precision. If specified as ``\'*\'`` (an asterisk), the actual\n precision is read from the next element of the tuple in *values*,\n and the value to convert comes after the precision.\n\n6. Length modifier (optional).\n\n7. Conversion type.\n\nWhen the right argument is a dictionary (or other mapping type), then\nthe formats in the string *must* include a parenthesised mapping key\ninto that dictionary inserted immediately after the ``\'%\'`` character.\nThe mapping key selects the value to be formatted from the mapping.\nFor example:\n\n>>> print(\'%(language)s has %(number)03d quote types.\' %\n... {\'language\': "Python", "number": 2})\nPython has 002 quote types.\n\nIn this case no ``*`` specifiers may occur in a format (since they\nrequire a sequential parameter list).\n\nThe conversion flag characters are:\n\n+-----------+-----------------------------------------------------------------------+\n| Flag | Meaning |\n+===========+=======================================================================+\n| ``\'#\'`` | The value conversion will use the "alternate form" (where defined |\n| | below). |\n+-----------+-----------------------------------------------------------------------+\n| ``\'0\'`` | The conversion will be zero padded for numeric values. |\n+-----------+-----------------------------------------------------------------------+\n| ``\'-\'`` | The converted value is left adjusted (overrides the ``\'0\'`` |\n| | conversion if both are given). |\n+-----------+-----------------------------------------------------------------------+\n| ``\' \'`` | (a space) A blank should be left before a positive number (or empty |\n| | string) produced by a signed conversion. |\n+-----------+-----------------------------------------------------------------------+\n| ``\'+\'`` | A sign character (``\'+\'`` or ``\'-\'``) will precede the conversion |\n| | (overrides a "space" flag). |\n+-----------+-----------------------------------------------------------------------+\n\nA length modifier (``h``, ``l``, or ``L``) may be present, but is\nignored as it is not necessary for Python -- so e.g. ``%ld`` is\nidentical to ``%d``.\n\nThe conversion types are:\n\n+--------------+-------------------------------------------------------+---------+\n| Conversion | Meaning | Notes |\n+==============+=======================================================+=========+\n| ``\'d\'`` | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'i\'`` | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'o\'`` | Signed octal value. | (1) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'u\'`` | Obsolete type -- it is identical to ``\'d\'``. | (7) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'x\'`` | Signed hexadecimal (lowercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'X\'`` | Signed hexadecimal (uppercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'e\'`` | Floating point exponential format (lowercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'E\'`` | Floating point exponential format (uppercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'f\'`` | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'F\'`` | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'g\'`` | Floating point format. Uses lowercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'G\'`` | Floating point format. Uses uppercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'c\'`` | Single character (accepts integer or single character | |\n| | string). | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'r\'`` | String (converts any Python object using ``repr()``). | (5) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'s\'`` | String (converts any Python object using ``str()``). | (5) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'a\'`` | String (converts any Python object using | (5) |\n| | ``ascii()``). | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'%\'`` | No argument is converted, results in a ``\'%\'`` | |\n| | character in the result. | |\n+--------------+-------------------------------------------------------+---------+\n\nNotes:\n\n1. The alternate form causes a leading zero (``\'0\'``) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n2. The alternate form causes a leading ``\'0x\'`` or ``\'0X\'`` (depending\n on whether the ``\'x\'`` or ``\'X\'`` format was used) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n3. The alternate form causes the result to always contain a decimal\n point, even if no digits follow it.\n\n The precision determines the number of digits after the decimal\n point and defaults to 6.\n\n4. The alternate form causes the result to always contain a decimal\n point, and trailing zeroes are not removed as they would otherwise\n be.\n\n The precision determines the number of significant digits before\n and after the decimal point and defaults to 6.\n\n5. If precision is ``N``, the output is truncated to ``N`` characters.\n\n1. See **PEP 237**.\n\nSince Python strings have an explicit length, ``%s`` conversions do\nnot assume that ``\'\\0\'`` is the end of the string.\n\nChanged in version 3.1: ``%f`` conversions for numbers whose absolute\nvalue is over 1e50 are no longer replaced by ``%g`` conversions.\n\nAdditional string operations are defined in standard modules\n``string`` and ``re``.\n\n\nRange Type\n==========\n\nThe ``range`` type is an immutable sequence which is commonly used for\nlooping. The advantage of the ``range`` type is that an ``range``\nobject will always take the same amount of memory, no matter the size\nof the range it represents.\n\nRange objects have relatively little behavior: they support indexing,\ncontains, iteration, the ``len()`` function, and the following\nmethods:\n\nrange.count(x)\n\n Return the number of *i*\'s for which ``s[i] == x``.\n\n New in version 3.2.\n\nrange.index(x)\n\n Return the smallest *i* such that ``s[i] == x``. Raises\n ``ValueError`` when *x* is not in the range.\n\n New in version 3.2.\n\n\nMutable Sequence Types\n======================\n\nList and bytearray objects support additional operations that allow\nin-place modification of the object. Other mutable sequence types\n(when added to the language) should also support these operations.\nStrings and tuples are immutable sequence types: such objects cannot\nbe modified once created. The following operations are defined on\nmutable sequence types (where *x* is an arbitrary object).\n\nNote that while lists allow their items to be of any type, bytearray\nobject "items" are all integers in the range 0 <= x < 256.\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | same as ``s[len(s):len(s)] = | |\n| | [x]`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(x)`` | same as ``s[len(s):len(s)] = x`` | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.clear()`` | remove all items from ``s`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.copy()`` | return a shallow copy of ``s`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.count(x)`` | return number of *i*\'s for which | |\n| | ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.index(x[, i[, j]])`` | return smallest *k* such that | (3) |\n| | ``s[k] == x`` and ``i <= k < j`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | same as ``s[i:i] = [x]`` | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | same as ``x = s[i]; del s[i]; | (5) |\n| | return x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | same as ``del s[s.index(x)]`` | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (6) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.sort([key[, reverse]])`` | sort the items of *s* in place | (6), (7), (8) |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. *x* can be any iterable object.\n\n3. Raises ``ValueError`` when *x* is not found in *s*. When a negative\n index is passed as the second or third parameter to the ``index()``\n method, the sequence length is added, as for slice indices. If it\n is still negative, it is truncated to zero, as for slice indices.\n\n4. When a negative index is passed as the first parameter to the\n ``insert()`` method, the sequence length is added, as for slice\n indices. If it is still negative, it is truncated to zero, as for\n slice indices.\n\n5. The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n6. The ``sort()`` and ``reverse()`` methods modify the sequence in\n place for economy of space when sorting or reversing a large\n sequence. To remind you that they operate by side effect, they\n don\'t return the sorted or reversed sequence.\n\n7. The ``sort()`` method takes optional arguments for controlling the\n comparisons. Each must be specified as a keyword argument.\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: ``key=str.lower``. The\n default value is ``None``. Use ``functools.cmp_to_key()`` to\n convert an old-style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n The ``sort()`` method is guaranteed to be stable. A sort is stable\n if it guarantees not to change the relative order of elements that\n compare equal --- this is helpful for sorting in multiple passes\n (for example, sort by department, then by salary grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises ``ValueError`` if it can detect\n that the list has been mutated during a sort.\n\n8. ``sort()`` is not supported by ``bytearray`` objects.\n\n New in version 3.3: ``clear()`` and ``copy()`` methods.\n\n\nBytes and Byte Array Methods\n============================\n\nBytes and bytearray objects, being "strings of bytes", have all\nmethods found on strings, with the exception of ``encode()``,\n``format()`` and ``isidentifier()``, which do not make sense with\nthese types. For converting the objects to strings, they have a\n``decode()`` method.\n\nWherever one of these methods needs to interpret the bytes as\ncharacters (e.g. the ``is...()`` methods), the ASCII character set is\nassumed.\n\nNew in version 3.3: The functions ``count()``, ``find()``,\n``index()``, ``rfind()`` and ``rindex()`` have additional semantics\ncompared to the corresponding string functions: They also accept an\ninteger in range 0 to 255 (a byte) as their first argument.\n\nNote: The methods on bytes and bytearray objects don\'t accept strings as\n their arguments, just as the methods on strings don\'t accept bytes\n as their arguments. For example, you have to write\n\n a = "abc"\n b = a.replace("a", "f")\n\n and\n\n a = b"abc"\n b = a.replace(b"a", b"f")\n\nbytes.decode(encoding="utf-8", errors="strict")\nbytearray.decode(encoding="utf-8", errors="strict")\n\n Return a string decoded from the given bytes. Default encoding is\n ``\'utf-8\'``. *errors* may be given to set a different error\n handling scheme. The default for *errors* is ``\'strict\'``, meaning\n that encoding errors raise a ``UnicodeError``. Other possible\n values are ``\'ignore\'``, ``\'replace\'`` and any other name\n registered via ``codecs.register_error()``, see section *Codec Base\n Classes*. For a list of possible encodings, see section *Standard\n Encodings*.\n\n Changed in version 3.1: Added support for keyword arguments.\n\nThe bytes and bytearray types have an additional class method:\n\nclassmethod bytes.fromhex(string)\nclassmethod bytearray.fromhex(string)\n\n This ``bytes`` class method returns a bytes or bytearray object,\n decoding the given string object. The string must contain two\n hexadecimal digits per byte, spaces are ignored.\n\n >>> bytes.fromhex(\'f0 f1f2 \')\n b\'\\xf0\\xf1\\xf2\'\n\nThe maketrans and translate methods differ in semantics from the\nversions available on strings:\n\nbytes.translate(table[, delete])\nbytearray.translate(table[, delete])\n\n Return a copy of the bytes or bytearray object where all bytes\n occurring in the optional argument *delete* are removed, and the\n remaining bytes have been mapped through the given translation\n table, which must be a bytes object of length 256.\n\n You can use the ``bytes.maketrans()`` method to create a\n translation table.\n\n Set the *table* argument to ``None`` for translations that only\n delete characters:\n\n >>> b\'read this short text\'.translate(None, b\'aeiou\')\n b\'rd ths shrt txt\'\n\nstatic bytes.maketrans(from, to)\nstatic bytearray.maketrans(from, to)\n\n This static method returns a translation table usable for\n ``bytes.translate()`` that will map each character in *from* into\n the character at the same position in *to*; *from* and *to* must be\n bytes objects and have the same length.\n\n New in version 3.1.\n', 'typesseq-mutable': '\nMutable Sequence Types\n**********************\n\nList and bytearray objects support additional operations that allow\nin-place modification of the object. Other mutable sequence types\n(when added to the language) should also support these operations.\nStrings and tuples are immutable sequence types: such objects cannot\nbe modified once created. The following operations are defined on\nmutable sequence types (where *x* is an arbitrary object).\n\nNote that while lists allow their items to be of any type, bytearray\nobject "items" are all integers in the range 0 <= x < 256.\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | same as ``s[len(s):len(s)] = | |\n| | [x]`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(x)`` | same as ``s[len(s):len(s)] = x`` | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.clear()`` | remove all items from ``s`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.copy()`` | return a shallow copy of ``s`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.count(x)`` | return number of *i*\'s for which | |\n| | ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.index(x[, i[, j]])`` | return smallest *k* such that | (3) |\n| | ``s[k] == x`` and ``i <= k < j`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | same as ``s[i:i] = [x]`` | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | same as ``x = s[i]; del s[i]; | (5) |\n| | return x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | same as ``del s[s.index(x)]`` | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (6) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.sort([key[, reverse]])`` | sort the items of *s* in place | (6), (7), (8) |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. *x* can be any iterable object.\n\n3. Raises ``ValueError`` when *x* is not found in *s*. When a negative\n index is passed as the second or third parameter to the ``index()``\n method, the sequence length is added, as for slice indices. If it\n is still negative, it is truncated to zero, as for slice indices.\n\n4. When a negative index is passed as the first parameter to the\n ``insert()`` method, the sequence length is added, as for slice\n indices. If it is still negative, it is truncated to zero, as for\n slice indices.\n\n5. The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n6. The ``sort()`` and ``reverse()`` methods modify the sequence in\n place for economy of space when sorting or reversing a large\n sequence. To remind you that they operate by side effect, they\n don\'t return the sorted or reversed sequence.\n\n7. The ``sort()`` method takes optional arguments for controlling the\n comparisons. Each must be specified as a keyword argument.\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: ``key=str.lower``. The\n default value is ``None``. Use ``functools.cmp_to_key()`` to\n convert an old-style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n The ``sort()`` method is guaranteed to be stable. A sort is stable\n if it guarantees not to change the relative order of elements that\n compare equal --- this is helpful for sorting in multiple passes\n (for example, sort by department, then by salary grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises ``ValueError`` if it can detect\n that the list has been mutated during a sort.\n\n8. ``sort()`` is not supported by ``bytearray`` objects.\n\n New in version 3.3: ``clear()`` and ``copy()`` methods.\n', 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary ``-`` (minus) operator yields the negation of its numeric\nargument.\n\nThe unary ``+`` (plus) operator yields its numeric argument unchanged.\n\nThe unary ``~`` (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of ``x`` is defined as\n``-(x+1)``. It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n``TypeError`` exception is raised.\n', 'while': '\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\nexecuted and the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ngoes back to testing the expression.\n', -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 13:48:28 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 01 Apr 2012 13:48:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_markup_errors_found_by_?= =?utf8?q?=22make_suspicious=22=2E?= Message-ID: http://hg.python.org/cpython/rev/6fce4022f86b changeset: 76044:6fce4022f86b user: Georg Brandl date: Sun Apr 01 13:48:26 2012 +0200 summary: Fix markup errors found by "make suspicious". files: Doc/library/unittest.mock-examples.rst | 2 +- Doc/library/unittest.mock.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -39,7 +39,7 @@ Once the mock has been called its :attr:`~Mock.called` attribute is set to `True`. More importantly we can use the :meth:`~Mock.assert_called_with` or -:meth`~Mock.assert_called_once_with` method to check that it was called with +:meth:`~Mock.assert_called_once_with` method to check that it was called with the correct arguments. This example tests that calling `ProductionClass().method` results in a call to diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -1712,9 +1712,9 @@ .. function:: call(*args, **kwargs) - `call` is a helper object for making simpler assertions, for comparing - with :attr:`~Mock.call_args`, :attr:`~Mock.call_args_list`, - :attr:`~Mock.mock_calls` and :attr: `~Mock.method_calls`. `call` can also be + `call` is a helper object for making simpler assertions, for comparing with + :attr:`~Mock.call_args`, :attr:`~Mock.call_args_list`, + :attr:`~Mock.mock_calls` and :attr:`~Mock.method_calls`. `call` can also be used with :meth:`~Mock.assert_has_calls`. >>> m = MagicMock(return_value=None) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 13:49:38 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 01 Apr 2012 13:49:38 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Bump_to_3=2E3=2E0a2=2E?= Message-ID: http://hg.python.org/cpython/rev/2f69db52d6de changeset: 76045:2f69db52d6de tag: v3.3.0a2 user: Georg Brandl date: Sun Apr 01 13:49:21 2012 +0200 summary: Bump to 3.3.0a2. files: Include/patchlevel.h | 4 ++-- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 2 +- Misc/RPM/python-3.3.spec | 2 +- README | 2 +- 6 files changed, 7 insertions(+), 7 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 3 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.3.0a1+" +#define PY_VERSION "3.3.0a2" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.3.0a1" +__version__ = "3.3.0a2" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.3.0a1" +IDLE_VERSION = "3.3.0a2" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,7 +5,7 @@ What's New in Python 3.3.0 Alpha 2? =================================== -*Release date: XXXX-XX-XX* +*Release date: 01-Apr-2012* Core and Builtins ----------------- diff --git a/Misc/RPM/python-3.3.spec b/Misc/RPM/python-3.3.spec --- a/Misc/RPM/python-3.3.spec +++ b/Misc/RPM/python-3.3.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.3.0a1 +%define version 3.3.0a2 %define libvers 3.3 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.3.0 alpha 1 +This is Python version 3.3.0 alpha 2 ==================================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 13:49:39 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 01 Apr 2012 13:49:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Added_tag_v3=2E3=2E0a2_for_?= =?utf8?q?changeset_2f69db52d6de?= Message-ID: http://hg.python.org/cpython/rev/90bc4b367fcb changeset: 76046:90bc4b367fcb user: Georg Brandl date: Sun Apr 01 13:49:38 2012 +0200 summary: Added tag v3.3.0a2 for changeset 2f69db52d6de files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -97,3 +97,4 @@ 7085403daf439adb3f9e70ef13f6bedb1c447376 v3.2.3rc1 428f05cb7277e1d42bb9dd8d1af6b6270ebc6112 v3.2.3rc2 f1a9a6505731714f0e157453ff850e3b71615c45 v3.3.0a1 +2f69db52d6de306cdaef0a0cc00cc823fb350b01 v3.3.0a2 -- Repository URL: http://hg.python.org/cpython From kristjan at ccpgames.com Sun Apr 1 14:31:57 2012 From: kristjan at ccpgames.com (=?iso-8859-1?Q?Kristj=E1n_Valur_J=F3nsson?=) Date: Sun, 1 Apr 2012 12:31:57 +0000 Subject: [Python-checkins] cpython: Issue #14435: Add Misc/NEWS and Misc/ACKS In-Reply-To: References: , Message-ID: Wishing to cause minimal disruption, I actually read http://docs.python.org/devguide/committing.html where this file is mentioned as part of the commit checklist. Never knew it existed before. K ________________________________________ Fr?: python-checkins-bounces+kristjan=ccpgames.com at python.org [python-checkins-bounces+kristjan=ccpgames.com at python.org] fyrir hönd Nick Coghlan [ncoghlan at gmail.com] Sent: 1. apr?l 2012 03:33 To: python-dev at python.org Cc: python-checkins at python.org Efni: Re: [Python-checkins] cpython: Issue #14435: Add Misc/NEWS and Misc/ACKS On Sat, Mar 31, 2012 at 11:10 PM, kristjan.jonsson wrote: > diff --git a/Misc/ACKS b/Misc/ACKS > --- a/Misc/ACKS > +++ b/Misc/ACKS > @@ -507,6 +507,7 @@ > Richard Jones > Irmen de Jong > Lucas de Jonge > +Kristj?n Valur J?nsson > Jens B. Jorgensen > John Jorgensen > Sijin Joseph *blinks* This must have been one of those cases where everyone assumed your name was already there and never thought to check... Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia _______________________________________________ Python-checkins mailing list Python-checkins at python.org http://mail.python.org/mailman/listinfo/python-checkins From python-checkins at python.org Sun Apr 1 16:14:42 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 01 Apr 2012 16:14:42 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzMDE5?= =?utf8?q?=3A_Fix_potential_reference_leaks_in_bytearray=2Eextend=28=29=2E?= Message-ID: http://hg.python.org/cpython/rev/03396c9ffe8c changeset: 76047:03396c9ffe8c branch: 3.2 parent: 76037:0a4a6f98bd8e user: Antoine Pitrou date: Sun Apr 01 16:05:46 2012 +0200 summary: Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch by Suman Saha. files: Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch + by Suman Saha. + - Issue #14378: Fix compiling ast.ImportFrom nodes with a "__future__" string as the module name that was not interned. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2234,8 +2234,10 @@ } bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); - if (bytearray_obj == NULL) + if (bytearray_obj == NULL) { + Py_DECREF(it); return NULL; + } buf = PyByteArray_AS_STRING(bytearray_obj); while ((item = PyIter_Next(it)) != NULL) { @@ -2268,8 +2270,10 @@ return NULL; } - if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) + if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) { + Py_DECREF(bytearray_obj); return NULL; + } Py_DECREF(bytearray_obj); Py_RETURN_NONE; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 16:14:43 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 01 Apr 2012 16:14:43 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2313019=3A_Fix_potential_reference_leaks_in_bytearray?= =?utf8?b?LmV4dGVuZCgpLg==?= Message-ID: http://hg.python.org/cpython/rev/015c546615ca changeset: 76048:015c546615ca parent: 76046:90bc4b367fcb parent: 76047:03396c9ffe8c user: Antoine Pitrou date: Sun Apr 01 16:08:11 2012 +0200 summary: Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch by Suman Saha. files: Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch + by Suman Saha. + - Issue #1683368: object.__new__ and object.__init__ raise a TypeError if they are passed arguments and their complementary method is not overridden. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2289,8 +2289,10 @@ } bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); - if (bytearray_obj == NULL) + if (bytearray_obj == NULL) { + Py_DECREF(it); return NULL; + } buf = PyByteArray_AS_STRING(bytearray_obj); while ((item = PyIter_Next(it)) != NULL) { @@ -2323,8 +2325,10 @@ return NULL; } - if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) + if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) { + Py_DECREF(bytearray_obj); return NULL; + } Py_DECREF(bytearray_obj); Py_RETURN_NONE; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 16:17:11 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 01 Apr 2012 16:17:11 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzMDE5?= =?utf8?q?=3A_Fix_potential_reference_leaks_in_bytearray=2Eextend=28=29=2E?= Message-ID: http://hg.python.org/cpython/rev/d3a82a26c705 changeset: 76049:d3a82a26c705 branch: 2.7 parent: 76036:3623c3e6c049 user: Antoine Pitrou date: Sun Apr 01 16:05:46 2012 +0200 summary: Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch by Suman Saha. files: Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ Core and Builtins ----------------- +- Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch + by Suman Saha. + - Issue #14378: Fix compiling ast.ImportFrom nodes with a "__future__" string as the module name that was not interned. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2296,8 +2296,10 @@ } bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); - if (bytearray_obj == NULL) + if (bytearray_obj == NULL) { + Py_DECREF(it); return NULL; + } buf = PyByteArray_AS_STRING(bytearray_obj); while ((item = PyIter_Next(it)) != NULL) { @@ -2330,8 +2332,10 @@ return NULL; } - if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) + if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) { + Py_DECREF(bytearray_obj); return NULL; + } Py_DECREF(bytearray_obj); Py_RETURN_NONE; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 16:41:47 2012 From: python-checkins at python.org (eli.bendersky) Date: Sun, 01 Apr 2012 16:41:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Removing_the_test_of_Elemen?= =?utf8?q?t_that_causes_ref-leak_in_GC_=28issue_=2314464=29=2E?= Message-ID: http://hg.python.org/cpython/rev/c5cf48752d81 changeset: 76050:c5cf48752d81 parent: 76048:015c546615ca user: Eli Bendersky date: Sun Apr 01 17:40:17 2012 +0300 summary: Removing the test of Element that causes ref-leak in GC (issue #14464). I will now continue investigating the cause of the ref-leak, but I wanted to remove the test so that the refcount test in the buildbots could be clean. The whole change (adding GC to Element) is not reverted because it improved the situation (GC works for immediate cycles) and didn't cause regressions (the test is new and was added together with the fix). files: Lib/test/test_xml_etree.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1859,16 +1859,6 @@ gc_collect() self.assertIsNone(wref()) - # A longer cycle: d->e->e2->d - e = ET.Element('joe') - d = Dummy() - d.dummyref = e - wref = weakref.ref(d) - e2 = ET.SubElement(e, 'foo', attr=d) - del d, e, e2 - gc_collect() - self.assertIsNone(wref()) - class ElementTreeTest(unittest.TestCase): def test_istype(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 17:30:58 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 01 Apr 2012 17:30:58 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0MTUx?= =?utf8?q?=3A_Raise_a_ValueError=2C_not_a_NameError=2C_when_trying_to_crea?= =?utf8?q?te?= Message-ID: http://hg.python.org/cpython/rev/273d7502ced1 changeset: 76051:273d7502ced1 branch: 3.2 parent: 76047:03396c9ffe8c user: Antoine Pitrou date: Sun Apr 01 17:19:09 2012 +0200 summary: Issue #14151: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. files: Lib/multiprocessing/connection.py | 9 +++++++++ Lib/test/test_multiprocessing.py | 14 +++++++++++++- Misc/NEWS | 4 ++++ 3 files changed, 26 insertions(+), 1 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -94,6 +94,13 @@ else: raise ValueError('unrecognized family') +def _validate_family(family): + ''' + Checks if the family is valid for the current environment. + ''' + if sys.platform != 'win32' and family == 'AF_PIPE': + raise ValueError('Family %s is not recognized.' % family) + def address_type(address): ''' @@ -126,6 +133,7 @@ or default_family address = address or arbitrary_address(family) + _validate_family(family) if family == 'AF_PIPE': self._listener = PipeListener(address, backlog) else: @@ -163,6 +171,7 @@ Returns a connection to the address of a `Listener` ''' family = family or address_type(address) + _validate_family(family) if family == 'AF_PIPE': c = PipeClient(address) else: diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2319,8 +2319,20 @@ flike.flush() assert sio.getvalue() == 'foo' + +# +# Issue 14151: Test invalid family on invalid environment +# + +class TestInvalidFamily(unittest.TestCase): + + @unittest.skipIf(WIN32, "skipped on Windows") + def test_invalid_family(self): + with self.assertRaises(ValueError): + multiprocessing.connection.Listener(r'\\.\test') + testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, - TestStdinBadfiledescriptor] + TestStdinBadfiledescriptor, TestInvalidFamily] # # diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,10 @@ Library ------- +- Issue #14151: Raise a ValueError, not a NameError, when trying to create + a multiprocessing Client or Listener with an AF_PIPE type address under + non-Windows platforms. Patch by Popa Claudiu. + - Issue #13872: socket.detach() now marks the socket closed (as mirrored in the socket repr()). Patch by Matt Joiner. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 17:30:59 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 01 Apr 2012 17:30:59 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314151=3A_Raise_a_ValueError=2C_not_a_NameError=2C_w?= =?utf8?q?hen_trying_to_create?= Message-ID: http://hg.python.org/cpython/rev/42b29aea1c98 changeset: 76052:42b29aea1c98 parent: 76050:c5cf48752d81 parent: 76051:273d7502ced1 user: Antoine Pitrou date: Sun Apr 01 17:25:49 2012 +0200 summary: Issue #14151: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. files: Lib/multiprocessing/connection.py | 9 +++++++++ Lib/test/test_multiprocessing.py | 14 +++++++++++++- Misc/NEWS | 4 ++++ 3 files changed, 26 insertions(+), 1 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -104,6 +104,13 @@ else: raise ValueError('unrecognized family') +def _validate_family(family): + ''' + Checks if the family is valid for the current environment. + ''' + if sys.platform != 'win32' and family == 'AF_PIPE': + raise ValueError('Family %s is not recognized.' % family) + def address_type(address): ''' @@ -436,6 +443,7 @@ or default_family address = address or arbitrary_address(family) + _validate_family(family) if family == 'AF_PIPE': self._listener = PipeListener(address, backlog) else: @@ -473,6 +481,7 @@ Returns a connection to the address of a `Listener` ''' family = family or address_type(address) + _validate_family(family) if family == 'AF_PIPE': c = PipeClient(address) else: diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2638,8 +2638,20 @@ p.join() +# +# Issue 14151: Test invalid family on invalid environment +# + +class TestInvalidFamily(unittest.TestCase): + + @unittest.skipIf(WIN32, "skipped on Windows") + def test_invalid_family(self): + with self.assertRaises(ValueError): + multiprocessing.connection.Listener(r'\\.\test') + + testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, - TestStdinBadfiledescriptor, TestWait] + TestStdinBadfiledescriptor, TestWait, TestInvalidFamily] # # diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,10 @@ Library ------- +- Issue #14151: Raise a ValueError, not a NameError, when trying to create + a multiprocessing Client or Listener with an AF_PIPE type address under + non-Windows platforms. Patch by Popa Claudiu. + - Issue #14300: Under Windows, sockets created using socket.dup() now allow overlapped I/O. Patch by sbt. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 18:32:09 2012 From: python-checkins at python.org (ross.lagerwall) Date: Sun, 01 Apr 2012 18:32:09 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_Issue_14467=3A_Simplify_Au?= =?utf8?q?toconf_section_and_move_it_to_FAQ=2E?= Message-ID: http://hg.python.org/devguide/rev/27be97280cff changeset: 499:27be97280cff user: Ross Lagerwall date: Sun Apr 01 18:31:12 2012 +0200 summary: Issue 14467: Simplify Autoconf section and move it to FAQ. files: faq.rst | 32 ++++++++++++++++++++++++ patch.rst | 56 ------------------------------------------- 2 files changed, 32 insertions(+), 56 deletions(-) diff --git a/faq.rst b/faq.rst --- a/faq.rst +++ b/faq.rst @@ -853,3 +853,35 @@ on which your keys are stored or the machine on which your keys are stored, be sure to report this to pydotorg at python.org at the same time that you change your keys. + + +General +======= + +How do I regenerate configure? +------------------------------ + +If a change is made to Python which relies on some POSIX system-specific +functionality (such as using a new system call), it is necessary to update the +``configure`` script to test for availability of the functionality. + +Python's ``configure`` script is generated from ``configure.ac`` using Autoconf. +Instead of editing ``configure``, edit ``configure.ac`` and then run +``autoreconf`` to regenerate ``configure`` and a number of other files (such as +``pyconfig.h``. + +When submitting a patch with changes made to ``configure.ac``, it is preferred +to leave out the generated files as differences between Autoconf versions +frequently results in many spurious changes cluttering the patch. Instead, +remind any potential reviewers on the tracker to run ``autoreconf``. + +Note that running ``autoreconf`` is not the same as running ``autoconf``. For +example, ``autoconf`` by itself will not regenerate ``pyconfig.h.in``. +``autoreconf`` runs ``autoconf`` and a number of other tools repeatedly as is +appropriate. + +Python's ``configure.ac`` script typically requires a specific version of +Autoconf. At the moment, this reads: ``version_required(2.65)`` + +If the system copy of Autoconf does not match this version, you will need to +install your own copy of Autoconf. diff --git a/patch.rst b/patch.rst --- a/patch.rst +++ b/patch.rst @@ -137,62 +137,6 @@ Also, please make sure your patch is whitespace normalized. ``patchcheck`` will check this for you. -Autoconf -'''''''' - -If a change is made to Python which relies on some POSIX system-specific -functionality (such as using a new system call), it is necessary to update the -``configure`` script to test for availability of the functionality. - -Python's ``configure`` script is generated from ``configure.ac`` using Autoconf. -Instead of editing ``configure``, edit ``configure.ac`` and then run -``autoreconf`` to regenerate ``configure`` and a number of other files (such as -``pyconfig.h``. - -When submitting a patch with changes made to ``configure.ac``, it is preferred -to leave out the generated files as differences between Autoconf versions -frequently results in many spurious changes cluttering the patch. Instead, -remind any potential reviewers on the tracker to run ``autoreconf``. - -Note that running ``autoreconf`` is not the same as running ``autoconf``. For -example, ``autoconf`` by itself will not regenerate ``pyconfig.h.in``. -``autoreconf`` runs ``autoconf`` and a number of other tools repeatedly as is -appropriate. - -Python's ``configure.ac`` script typically requires a specific version of -Autoconf. At the moment, this reads: ``version_required(2.65)`` - -If the system copy of Autoconf does not match this version, you will need to -install your own copy of Autoconf: - -1. Go to http://ftp.gnu.org/gnu/autoconf/ and download the version of Autoconf - matching the one in ``configure.ac``:: - - wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.65.tar.bz2 - -2. Unpack the tarball:: - - tar -jxf autoconf-2.65.tar.bz2 - -3. Build the specified version of Autoconf and install it to a writable location - (e.g. within your home directory):: - - pushd autoconf-2.65.tar.bz2 - ./configure --prefix=$HOME/autoconf-2.65 - make - make install - - This installs a copy of the appropriate version of Autoconf into - ~/autoconf-2.65. - -4. Go back to the Python source and rerun ``autoreconf``, pointing ``PATH`` at - the newly installed copy of Autoconf:: - - popd - PATH=~/autoconf-2.65/bin:$PATH autoreconf - -5. Autoconf should now have updated your local copy of ``configure`` to reflect - your changes. Submitting ---------- -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Apr 1 19:55:28 2012 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 01 Apr 2012 19:55:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Add_MASM_define_to_PGI_and_?= =?utf8?q?PGO_builds?= Message-ID: http://hg.python.org/cpython/rev/a8cacedf2ffc changeset: 76053:a8cacedf2ffc user: Martin v. L?wis date: Sun Apr 01 19:54:33 2012 +0200 summary: Add MASM define to PGI and PGO builds files: PCbuild/_decimal.vcproj | 1486 +++++++++++++------------- 1 files changed, 743 insertions(+), 743 deletions(-) diff --git a/PCbuild/_decimal.vcproj b/PCbuild/_decimal.vcproj --- a/PCbuild/_decimal.vcproj +++ b/PCbuild/_decimal.vcproj @@ -1,743 +1,743 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 19:56:21 2012 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 01 Apr 2012 19:56:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Add_=5Fdecimal_and_=5Ftestb?= =?utf8?q?uffer_modules=2E?= Message-ID: http://hg.python.org/cpython/rev/7ec7623b27ec changeset: 76054:7ec7623b27ec user: Martin v. L?wis date: Sun Apr 01 19:55:48 2012 +0200 summary: Add _decimal and _testbuffer modules. files: Tools/msi/msi.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py --- a/Tools/msi/msi.py +++ b/Tools/msi/msi.py @@ -97,7 +97,9 @@ '_sqlite3.pyd', '_hashlib.pyd', '_multiprocessing.pyd', - '_lzma.pyd' + '_lzma.pyd', + '_decimal.pyd', + '_testbuffer.pyd' ] # Well-known component UUIDs -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 1 23:27:04 2012 From: python-checkins at python.org (stefan.krah) Date: Sun, 01 Apr 2012 23:27:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_Overflow_exception_in_t?= =?utf8?q?he_bignum_factorial_benchmark_that_is_due_to?= Message-ID: http://hg.python.org/cpython/rev/1f5701ffa077 changeset: 76055:1f5701ffa077 user: Stefan Krah date: Sun Apr 01 23:25:34 2012 +0200 summary: Fix Overflow exception in the bignum factorial benchmark that is due to the recent change of the default value for context.Emax. files: Modules/_decimal/tests/bench.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Modules/_decimal/tests/bench.py b/Modules/_decimal/tests/bench.py --- a/Modules/_decimal/tests/bench.py +++ b/Modules/_decimal/tests/bench.py @@ -84,7 +84,10 @@ print("# Factorial") print("# ======================================================================\n") -C.getcontext().prec = C.MAX_PREC +c = C.getcontext() +c.prec = C.MAX_PREC +c.Emax = C.MAX_EMAX +c.Emin = C.MIN_EMIN for n in [100000, 1000000]: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 00:50:51 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 00:50:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_be_consistent_w?= =?utf8?q?ith_rest_of_function?= Message-ID: http://hg.python.org/cpython/rev/5bb0acb69921 changeset: 76056:5bb0acb69921 branch: 3.2 parent: 75941:66117d4bb586 user: Benjamin Peterson date: Sun Apr 01 18:48:02 2012 -0400 summary: be consistent with rest of function files: Objects/typeobject.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -475,9 +475,8 @@ new_base = best_base(value); - if (!new_base) { + if (!new_base) return -1; - } if (!compatible_for_assignment(type->tp_base, new_base, "__bases__")) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 00:50:52 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 00:50:52 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMik6?= =?utf8?q?_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/6b3713113ec9 changeset: 76057:6b3713113ec9 branch: 3.2 parent: 76056:5bb0acb69921 parent: 76051:273d7502ced1 user: Benjamin Peterson date: Sun Apr 01 18:48:11 2012 -0400 summary: merge heads files: Doc/glossary.rst | 2 +- Doc/library/argparse.rst | 9 +- Doc/library/logging.handlers.rst | 2 +- Doc/library/signal.rst | 78 +++++++++------- Doc/library/syslog.rst | 3 +- Doc/library/unittest.rst | 2 +- Doc/library/webbrowser.rst | 2 + Lib/concurrent/futures/_base.py | 8 +- Lib/idlelib/NEWS.txt | 5 + Lib/idlelib/configHandler.py | 2 +- Lib/logging/handlers.py | 15 ++- Lib/multiprocessing/connection.py | 9 + Lib/pydoc.py | 4 +- Lib/rlcompleter.py | 36 +++---- Lib/socket.py | 11 ++ Lib/test/test_concurrent_futures.py | 18 +++- Lib/test/test_multiprocessing.py | 14 ++- Lib/test/test_socket.py | 1 + Misc/NEWS | 20 ++++ Modules/_io/_iomodule.h | 2 +- Modules/python.c | 6 +- Objects/bytearrayobject.c | 8 +- 22 files changed, 178 insertions(+), 79 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -385,7 +385,7 @@ :meth:`str.lower` method can serve as a key function for case insensitive sorts. Alternatively, an ad-hoc key function can be built from a :keyword:`lambda` expression such as ``lambda r: (r[0], r[2])``. Also, - the :mod:`operator` module provides three key function constuctors: + the :mod:`operator` module provides three key function constructors: :func:`~operator.attrgetter`, :func:`~operator.itemgetter`, and :func:`~operator.methodcaller`. See the :ref:`Sorting HOW TO ` for examples of how to create and use key functions. diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1642,8 +1642,8 @@ --bar BAR bar help - Note that any arguments not your user defined groups will end up back in the - usual "positional arguments" and "optional arguments" sections. + Note that any arguments not in your user-defined groups will end up back + in the usual "positional arguments" and "optional arguments" sections. Mutual exclusion @@ -1833,9 +1833,10 @@ * Replace all :meth:`optparse.OptionParser.add_option` calls with :meth:`ArgumentParser.add_argument` calls. -* Replace ``options, args = parser.parse_args()`` with ``args = +* Replace ``(options, args) = parser.parse_args()`` with ``args = parser.parse_args()`` and add additional :meth:`ArgumentParser.add_argument` - calls for the positional arguments. + calls for the positional arguments. Keep in mind that what was previously + called ``options``, now in :mod:`argparse` context is called ``args``. * Replace callback actions and the ``callback_*`` keyword arguments with ``type`` or ``action`` arguments. diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -654,7 +654,7 @@ :class:`BufferingHandler`, which is an abstract class. This buffers logging records in memory. Whenever each record is added to the buffer, a check is made by calling :meth:`shouldFlush` to see if the buffer should be flushed. If it -should, then :meth:`flush` is expected to do the needful. +should, then :meth:`flush` is expected to do the flushing. .. class:: BufferingHandler(capacity) diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -5,46 +5,58 @@ :synopsis: Set handlers for asynchronous events. -This module provides mechanisms to use signal handlers in Python. Some general -rules for working with signals and their handlers: +This module provides mechanisms to use signal handlers in Python. -* A handler for a particular signal, once set, remains installed until it is - explicitly reset (Python emulates the BSD style interface regardless of the - underlying implementation), with the exception of the handler for - :const:`SIGCHLD`, which follows the underlying implementation. -* There is no way to "block" signals temporarily from critical sections (since - this is not supported by all Unix flavors). +General rules +------------- -* Although Python signal handlers are called asynchronously as far as the Python - user is concerned, they can only occur between the "atomic" instructions of the - Python interpreter. This means that signals arriving during long calculations - implemented purely in C (such as regular expression matches on large bodies of - text) may be delayed for an arbitrary amount of time. +The :func:`signal.signal` function allows to define custom handlers to be +executed when a signal is received. A small number of default handlers are +installed: :const:`SIGPIPE` is ignored (so write errors on pipes and sockets +can be reported as ordinary Python exceptions) and :const:`SIGINT` is +translated into a :exc:`KeyboardInterrupt` exception. -* When a signal arrives during an I/O operation, it is possible that the I/O - operation raises an exception after the signal handler returns. This is - dependent on the underlying Unix system's semantics regarding interrupted system - calls. +A handler for a particular signal, once set, remains installed until it is +explicitly reset (Python emulates the BSD style interface regardless of the +underlying implementation), with the exception of the handler for +:const:`SIGCHLD`, which follows the underlying implementation. -* Because the C signal handler always returns, it makes little sense to catch - synchronous errors like :const:`SIGFPE` or :const:`SIGSEGV`. +There is no way to "block" signals temporarily from critical sections (since +this is not supported by all Unix flavors). -* Python installs a small number of signal handlers by default: :const:`SIGPIPE` - is ignored (so write errors on pipes and sockets can be reported as ordinary - Python exceptions) and :const:`SIGINT` is translated into a - :exc:`KeyboardInterrupt` exception. All of these can be overridden. -* Some care must be taken if both signals and threads are used in the same - program. The fundamental thing to remember in using signals and threads - simultaneously is: always perform :func:`signal` operations in the main thread - of execution. Any thread can perform an :func:`alarm`, :func:`getsignal`, - :func:`pause`, :func:`setitimer` or :func:`getitimer`; only the main thread - can set a new signal handler, and the main thread will be the only one to - receive signals (this is enforced by the Python :mod:`signal` module, even - if the underlying thread implementation supports sending signals to - individual threads). This means that signals can't be used as a means of - inter-thread communication. Use locks instead. +Execution of Python signal handlers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A Python signal handler does not get executed inside the low-level (C) signal +handler. Instead, the low-level signal handler sets a flag which tells the +:term:`virtual machine` to execute the corresponding Python signal handler +at a later point(for example at the next :term:`bytecode` instruction). +This has consequences: + +* It makes little sense to catch synchronous errors like :const:`SIGFPE` or + :const:`SIGSEGV`. + +* A long-running calculation implemented purely in C (such as regular + expression matching on a large body of text) may run uninterrupted for an + arbitrary amount of time, regardless of any signals received. The Python + signal handlers will be called when the calculation finishes. + + +Signals and threads +^^^^^^^^^^^^^^^^^^^ + +Python signal handlers are always executed in the main Python thread, +even if the signal was received in another thread. This means that signals +can't be used as a means of inter-thread communication. You can use +the synchronization primitives from the :mod:`threading` module instead. + +Besides, only the main thread is allowed to set a new signal handler. + + +Module contents +--------------- The variables defined in the :mod:`signal` module are: diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -78,7 +78,8 @@ Facilities: :const:`LOG_KERN`, :const:`LOG_USER`, :const:`LOG_MAIL`, :const:`LOG_DAEMON`, :const:`LOG_AUTH`, :const:`LOG_LPR`, :const:`LOG_NEWS`, :const:`LOG_UUCP`, - :const:`LOG_CRON` and :const:`LOG_LOCAL0` to :const:`LOG_LOCAL7`. + :const:`LOG_CRON`, :const:`LOG_SYSLOG` and :const:`LOG_LOCAL0` to + :const:`LOG_LOCAL7`. Log options: :const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, :const:`LOG_NOWAIT` diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -640,7 +640,7 @@ Classes can be skipped just like methods: :: - @skip("showing class skipping") + @unittest.skip("showing class skipping") class MySkippedTestCase(unittest.TestCase): def test_not_run(self): pass diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -137,6 +137,8 @@ +-----------------------+-----------------------------------------+-------+ | ``'macosx'`` | :class:`MacOSX('default')` | \(4) | +-----------------------+-----------------------------------------+-------+ +| ``'safari'`` | :class:`MacOSX('safari')` | \(4) | ++-----------------------+-----------------------------------------+-------+ Notes: diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -112,12 +112,14 @@ def __init__(self, num_pending_calls, stop_on_exception): self.num_pending_calls = num_pending_calls self.stop_on_exception = stop_on_exception + self.lock = threading.Lock() super().__init__() def _decrement_pending_calls(self): - self.num_pending_calls -= 1 - if not self.num_pending_calls: - self.event.set() + with self.lock: + self.num_pending_calls -= 1 + if not self.num_pending_calls: + self.event.set() def add_result(self, future): super().add_result(future) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,6 +1,11 @@ What's New in IDLE 3.2.3? ========================= +- Issue #14409: IDLE now properly executes commands in the Shell window + when it cannot read the normal config files on startup and + has to use the built-in default key bindings. + There was previously a bug in one of the defaults. + - Issue #3573: IDLE hangs when passing invalid command line args (directory(ies) instead of file(s)). diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -595,7 +595,7 @@ '<>': [''], '<>': [''], '<>': [''], - '<>': [' '], + '<>': ['', ''], '<>': [''], '<>': [''], '<>': [''], diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -519,11 +519,16 @@ """ ei = record.exc_info if ei: - dummy = self.format(record) # just to get traceback text into record.exc_text - record.exc_info = None # to avoid Unpickleable error - s = pickle.dumps(record.__dict__, 1) - if ei: - record.exc_info = ei # for next handler + # just to get traceback text into record.exc_text ... + dummy = self.format(record) + # See issue #14436: If msg or args are objects, they may not be + # available on the receiving end. So we convert the msg % args + # to a string, save it as msg and zap the args. + d = dict(record.__dict__) + d['msg'] = record.getMessage() + d['args'] = None + d['exc_info'] = None + s = pickle.dumps(d, 1) slen = struct.pack(">L", len(s)) return slen + s diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -94,6 +94,13 @@ else: raise ValueError('unrecognized family') +def _validate_family(family): + ''' + Checks if the family is valid for the current environment. + ''' + if sys.platform != 'win32' and family == 'AF_PIPE': + raise ValueError('Family %s is not recognized.' % family) + def address_type(address): ''' @@ -126,6 +133,7 @@ or default_family address = address or arbitrary_address(family) + _validate_family(family) if family == 'AF_PIPE': self._listener = PipeListener(address, backlog) else: @@ -163,6 +171,7 @@ Returns a connection to the address of a `Listener` ''' family = family or address_type(address) + _validate_family(family) if family == 'AF_PIPE': c = PipeClient(address) else: diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1829,7 +1829,7 @@ Welcome to Python %s! This is the online help utility. If this is your first time using Python, you should definitely check out -the tutorial on the Internet at http://docs.python.org/tutorial/. +the tutorial on the Internet at http://docs.python.org/%s/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and @@ -1839,7 +1839,7 @@ "keywords", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose summaries contain a given word such as "spam", type "modules spam". -''' % sys.version[:3]) +''' % tuple([sys.version[:3]]*2)) def list(self, items, columns=4, width=80): items = list(sorted(items)) diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -1,13 +1,11 @@ -"""Word completion for GNU readline 2.0. +"""Word completion for GNU readline. -This requires the latest extension to the readline module. The completer -completes keywords, built-ins and globals in a selectable namespace (which -defaults to __main__); when completing NAME.NAME..., it evaluates (!) the -expression up to the last dot and completes its attributes. +The completer completes keywords, built-ins and globals in a selectable +namespace (which defaults to __main__); when completing NAME.NAME..., it +evaluates (!) the expression up to the last dot and completes its attributes. -It's very cool to do "import sys" type "sys.", hit the -completion key (twice), and see the list of names defined by the -sys module! +It's very cool to do "import sys" type "sys.", hit the completion key (twice), +and see the list of names defined by the sys module! Tip: to use the tab key as the completion key, call @@ -15,21 +13,19 @@ Notes: -- Exceptions raised by the completer function are *ignored* (and -generally cause the completion to fail). This is a feature -- since -readline sets the tty device in raw (or cbreak) mode, printing a -traceback wouldn't work well without some complicated hoopla to save, -reset and restore the tty state. +- Exceptions raised by the completer function are *ignored* (and generally cause + the completion to fail). This is a feature -- since readline sets the tty + device in raw (or cbreak) mode, printing a traceback wouldn't work well + without some complicated hoopla to save, reset and restore the tty state. -- The evaluation of the NAME.NAME... form may cause arbitrary -application defined code to be executed if an object with a -__getattr__ hook is found. Since it is the responsibility of the -application (or the user) to enable this feature, I consider this an -acceptable risk. More complicated expressions (e.g. function calls or -indexing operations) are *not* evaluated. +- The evaluation of the NAME.NAME... form may cause arbitrary application + defined code to be executed if an object with a __getattr__ hook is found. + Since it is the responsibility of the application (or the user) to enable this + feature, I consider this an acceptable risk. More complicated expressions + (e.g. function calls or indexing operations) are *not* evaluated. - When the original stdin is not a tty device, GNU readline is never -used, and this module (and the readline module) are silently inactive. + used, and this module (and the readline module) are silently inactive. """ diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -197,6 +197,17 @@ if self._io_refs <= 0: self._real_close() + def detach(self): + """detach() -> file descriptor + + Close the socket object without closing the underlying file descriptor. + The object cannot be used after this call, but the file descriptor + can be reused for other purposes. The file descriptor is returned. + """ + self._closed = True + return super().detach() + + def fromfd(fd, family, type, proto=0): """ fromfd(fd, family, type[, proto]) -> socket object diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -183,7 +183,9 @@ for p in processes: p.join() + class WaitTests(unittest.TestCase): + def test_first_completed(self): future1 = self.executor.submit(mul, 21, 2) future2 = self.executor.submit(time.sleep, 1.5) @@ -284,7 +286,21 @@ class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests): - pass + + def test_pending_calls_race(self): + # Issue #14406: multi-threaded race condition when waiting on all + # futures. + event = threading.Event() + def future_func(): + event.wait() + oldswitchinterval = sys.getswitchinterval() + sys.setswitchinterval(1e-6) + try: + fs = {self.executor.submit(future_func) for i in range(100)} + event.set() + futures.wait(fs, return_when=futures.ALL_COMPLETED) + finally: + sys.setswitchinterval(oldswitchinterval) class ProcessPoolWaitTests(ProcessPoolMixin, WaitTests): diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2319,8 +2319,20 @@ flike.flush() assert sio.getvalue() == 'foo' + +# +# Issue 14151: Test invalid family on invalid environment +# + +class TestInvalidFamily(unittest.TestCase): + + @unittest.skipIf(WIN32, "skipped on Windows") + def test_invalid_family(self): + with self.assertRaises(ValueError): + multiprocessing.connection.Listener(r'\\.\test') + testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, - TestStdinBadfiledescriptor] + TestStdinBadfiledescriptor, TestInvalidFamily] # # 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 @@ -951,6 +951,7 @@ f = self.cli_conn.detach() self.assertEqual(f, fileno) # cli_conn cannot be used anymore... + self.assertTrue(self.cli_conn._closed) self.assertRaises(socket.error, self.cli_conn.recv, 1024) self.cli_conn.close() # ...but we can create another socket using the (still open) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch + by Suman Saha. + - Issue #14378: Fix compiling ast.ImportFrom nodes with a "__future__" string as the module name that was not interned. @@ -31,6 +34,21 @@ Library ------- +- Issue #14151: Raise a ValueError, not a NameError, when trying to create + a multiprocessing Client or Listener with an AF_PIPE type address under + non-Windows platforms. Patch by Popa Claudiu. + +- Issue #13872: socket.detach() now marks the socket closed (as mirrored + in the socket repr()). Patch by Matt Joiner. + +- Issue #14406: Fix a race condition when using ``concurrent.futures.wait( + return_when=ALL_COMPLETED)``. Patch by Matt Joiner. + +- Issue #14409: IDLE now properly executes commands in the Shell window + when it cannot read the normal config files on startup and + has to use the built-in default key bindings. + There was previously a bug in one of the defaults. + - Issue #10340: asyncore - properly handle EINVAL in dispatcher constructor on OSX; avoid to call handle_connect in case of a disconnected socket which was not meant to connect. @@ -97,6 +115,8 @@ Build ----- +- Issue #14437: Fix building the _io module under Cygwin. + - Issue #14387: Do not include accu.h from Python.h. - Issue #14359: Only use O_CLOEXEC in _posixmodule.c if it is defined. diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -67,7 +67,7 @@ PyObject *filename; /* Not used, but part of the IOError object */ Py_ssize_t written; } PyBlockingIOErrorObject; -PyAPI_DATA(PyObject *) PyExc_BlockingIOError; +extern PyObject *PyExc_BlockingIOError; /* * Offset type for positioning. diff --git a/Modules/python.c b/Modules/python.c --- a/Modules/python.c +++ b/Modules/python.c @@ -22,9 +22,9 @@ int main(int argc, char **argv) { - wchar_t **argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*argc); + wchar_t **argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*(argc+1)); /* We need a second copies, as Python might modify the first one. */ - wchar_t **argv_copy2 = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*argc); + wchar_t **argv_copy2 = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*(argc+1)); int i, res; char *oldloc; /* 754 requires that FP exceptions run in "no stop" mode by default, @@ -58,6 +58,8 @@ } argv_copy2[i] = argv_copy[i]; } + argv_copy2[argc] = argv_copy[argc] = NULL; + setlocale(LC_ALL, oldloc); free(oldloc); res = Py_Main(argc, argv_copy); diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2234,8 +2234,10 @@ } bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); - if (bytearray_obj == NULL) + if (bytearray_obj == NULL) { + Py_DECREF(it); return NULL; + } buf = PyByteArray_AS_STRING(bytearray_obj); while ((item = PyIter_Next(it)) != NULL) { @@ -2268,8 +2270,10 @@ return NULL; } - if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) + if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) { + Py_DECREF(bytearray_obj); return NULL; + } Py_DECREF(bytearray_obj); Py_RETURN_NONE; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 00:50:53 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 00:50:53 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_remove_extraneo?= =?utf8?q?us_condition?= Message-ID: http://hg.python.org/cpython/rev/c1fff85711a6 changeset: 76058:c1fff85711a6 branch: 3.2 user: Benjamin Peterson date: Sun Apr 01 18:48:40 2012 -0400 summary: remove extraneous condition files: Objects/typeobject.c | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -464,12 +464,10 @@ type->tp_name, Py_TYPE(ob)->tp_name); return -1; } - if (PyType_Check(ob)) { - if (PyType_IsSubtype((PyTypeObject*)ob, type)) { - PyErr_SetString(PyExc_TypeError, - "a __bases__ item causes an inheritance cycle"); - return -1; - } + if (PyType_IsSubtype((PyTypeObject*)ob, type)) { + PyErr_SetString(PyExc_TypeError, + "a __bases__ item causes an inheritance cycle"); + return -1; } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 00:50:54 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 00:50:54 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_adjust_formatti?= =?utf8?q?ng?= Message-ID: http://hg.python.org/cpython/rev/d746ffc34e0f changeset: 76059:d746ffc34e0f branch: 3.2 user: Benjamin Peterson date: Sun Apr 01 18:49:54 2012 -0400 summary: adjust formatting files: Objects/typeobject.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -458,11 +458,11 @@ for (i = 0; i < PyTuple_GET_SIZE(value); i++) { ob = PyTuple_GET_ITEM(value, i); if (!PyType_Check(ob)) { - PyErr_Format( - PyExc_TypeError, - "%s.__bases__ must be tuple of old- or new-style classes, not '%s'", - type->tp_name, Py_TYPE(ob)->tp_name); - return -1; + PyErr_Format(PyExc_TypeError, + "%s.__bases__ must be tuple of old- or " + "new-style classes, not '%s'", + type->tp_name, Py_TYPE(ob)->tp_name); + return -1; } if (PyType_IsSubtype((PyTypeObject*)ob, type)) { PyErr_SetString(PyExc_TypeError, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 00:51:44 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 00:51:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/1c80a7bcbd6b changeset: 76060:1c80a7bcbd6b parent: 76055:1f5701ffa077 parent: 76059:d746ffc34e0f user: Benjamin Peterson date: Sun Apr 01 18:51:37 2012 -0400 summary: merge 3.2 files: Objects/typeobject.c | 22 +++++++++------------- 1 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -490,26 +490,22 @@ for (i = 0; i < PyTuple_GET_SIZE(value); i++) { ob = PyTuple_GET_ITEM(value, i); if (!PyType_Check(ob)) { - PyErr_Format( - PyExc_TypeError, - "%s.__bases__ must be tuple of classes, not '%s'", - type->tp_name, Py_TYPE(ob)->tp_name); - return -1; + PyErr_Format(PyExc_TypeError, + "%s.__bases__ must be tuple of classes, not '%s'", + type->tp_name, Py_TYPE(ob)->tp_name); + return -1; } - if (PyType_Check(ob)) { - if (PyType_IsSubtype((PyTypeObject*)ob, type)) { - PyErr_SetString(PyExc_TypeError, - "a __bases__ item causes an inheritance cycle"); - return -1; - } + if (PyType_IsSubtype((PyTypeObject*)ob, type)) { + PyErr_SetString(PyExc_TypeError, + "a __bases__ item causes an inheritance cycle"); + return -1; } } new_base = best_base(value); - if (!new_base) { + if (!new_base) return -1; - } if (!compatible_for_assignment(type->tp_base, new_base, "__bases__")) return -1; -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Apr 2 05:35:20 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 02 Apr 2012 05:35:20 +0200 Subject: [Python-checkins] Daily reference leaks (1c80a7bcbd6b): sum=0 Message-ID: results for 1c80a7bcbd6b on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogWSPbp7', '-x'] From python-checkins at python.org Mon Apr 2 07:52:24 2012 From: python-checkins at python.org (georg.brandl) Date: Mon, 02 Apr 2012 07:52:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Post-release_update=2E?= Message-ID: http://hg.python.org/cpython/rev/985cc819a70f changeset: 76061:985cc819a70f parent: 76046:90bc4b367fcb user: Georg Brandl date: Mon Apr 02 07:51:45 2012 +0200 summary: Post-release update. 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.3.0a2" +#define PY_VERSION "3.3.0a2+" /*--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.3.0 Alpha 3? +=================================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.3.0 Alpha 2? =================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 07:52:24 2012 From: python-checkins at python.org (georg.brandl) Date: Mon, 02 Apr 2012 07:52:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?b?KTogTWVyZ2Uu?= Message-ID: http://hg.python.org/cpython/rev/9fcb2676696c changeset: 76062:9fcb2676696c parent: 76061:985cc819a70f parent: 76060:1c80a7bcbd6b user: Georg Brandl date: Mon Apr 02 07:52:29 2012 +0200 summary: Merge. files: Lib/multiprocessing/connection.py | 9 + Lib/test/test_multiprocessing.py | 14 +- Lib/test/test_xml_etree.py | 10 - Misc/NEWS | 7 + Modules/_decimal/tests/bench.py | 5 +- Objects/bytearrayobject.c | 8 +- Objects/typeobject.c | 22 +- PCbuild/_decimal.vcproj | 1486 ++++++++-------- Tools/msi/msi.py | 4 +- 9 files changed, 794 insertions(+), 771 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -104,6 +104,13 @@ else: raise ValueError('unrecognized family') +def _validate_family(family): + ''' + Checks if the family is valid for the current environment. + ''' + if sys.platform != 'win32' and family == 'AF_PIPE': + raise ValueError('Family %s is not recognized.' % family) + def address_type(address): ''' @@ -436,6 +443,7 @@ or default_family address = address or arbitrary_address(family) + _validate_family(family) if family == 'AF_PIPE': self._listener = PipeListener(address, backlog) else: @@ -473,6 +481,7 @@ Returns a connection to the address of a `Listener` ''' family = family or address_type(address) + _validate_family(family) if family == 'AF_PIPE': c = PipeClient(address) else: diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2638,8 +2638,20 @@ p.join() +# +# Issue 14151: Test invalid family on invalid environment +# + +class TestInvalidFamily(unittest.TestCase): + + @unittest.skipIf(WIN32, "skipped on Windows") + def test_invalid_family(self): + with self.assertRaises(ValueError): + multiprocessing.connection.Listener(r'\\.\test') + + testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, - TestStdinBadfiledescriptor, TestWait] + TestStdinBadfiledescriptor, TestWait, TestInvalidFamily] # # diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1859,16 +1859,6 @@ gc_collect() self.assertIsNone(wref()) - # A longer cycle: d->e->e2->d - e = ET.Element('joe') - d = Dummy() - d.dummyref = e - wref = weakref.ref(d) - e2 = ET.SubElement(e, 'foo', attr=d) - del d, e, e2 - gc_collect() - self.assertIsNone(wref()) - class ElementTreeTest(unittest.TestCase): def test_istype(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,9 +10,16 @@ Core and Builtins ----------------- +- Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch + by Suman Saha. + Library ------- +- Issue #14151: Raise a ValueError, not a NameError, when trying to create + a multiprocessing Client or Listener with an AF_PIPE type address under + non-Windows platforms. Patch by Popa Claudiu. + What's New in Python 3.3.0 Alpha 2? =================================== diff --git a/Modules/_decimal/tests/bench.py b/Modules/_decimal/tests/bench.py --- a/Modules/_decimal/tests/bench.py +++ b/Modules/_decimal/tests/bench.py @@ -84,7 +84,10 @@ print("# Factorial") print("# ======================================================================\n") -C.getcontext().prec = C.MAX_PREC +c = C.getcontext() +c.prec = C.MAX_PREC +c.Emax = C.MAX_EMAX +c.Emin = C.MIN_EMIN for n in [100000, 1000000]: diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2289,8 +2289,10 @@ } bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); - if (bytearray_obj == NULL) + if (bytearray_obj == NULL) { + Py_DECREF(it); return NULL; + } buf = PyByteArray_AS_STRING(bytearray_obj); while ((item = PyIter_Next(it)) != NULL) { @@ -2323,8 +2325,10 @@ return NULL; } - if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) + if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) { + Py_DECREF(bytearray_obj); return NULL; + } Py_DECREF(bytearray_obj); Py_RETURN_NONE; diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -490,26 +490,22 @@ for (i = 0; i < PyTuple_GET_SIZE(value); i++) { ob = PyTuple_GET_ITEM(value, i); if (!PyType_Check(ob)) { - PyErr_Format( - PyExc_TypeError, - "%s.__bases__ must be tuple of classes, not '%s'", - type->tp_name, Py_TYPE(ob)->tp_name); - return -1; + PyErr_Format(PyExc_TypeError, + "%s.__bases__ must be tuple of classes, not '%s'", + type->tp_name, Py_TYPE(ob)->tp_name); + return -1; } - if (PyType_Check(ob)) { - if (PyType_IsSubtype((PyTypeObject*)ob, type)) { - PyErr_SetString(PyExc_TypeError, - "a __bases__ item causes an inheritance cycle"); - return -1; - } + if (PyType_IsSubtype((PyTypeObject*)ob, type)) { + PyErr_SetString(PyExc_TypeError, + "a __bases__ item causes an inheritance cycle"); + return -1; } } new_base = best_base(value); - if (!new_base) { + if (!new_base) return -1; - } if (!compatible_for_assignment(type->tp_base, new_base, "__bases__")) return -1; diff --git a/PCbuild/_decimal.vcproj b/PCbuild/_decimal.vcproj --- a/PCbuild/_decimal.vcproj +++ b/PCbuild/_decimal.vcproj @@ -1,743 +1,743 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py --- a/Tools/msi/msi.py +++ b/Tools/msi/msi.py @@ -97,7 +97,9 @@ '_sqlite3.pyd', '_hashlib.pyd', '_multiprocessing.pyd', - '_lzma.pyd' + '_lzma.pyd', + '_decimal.pyd', + '_testbuffer.pyd' ] # Well-known component UUIDs -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 15:13:18 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 02 Apr 2012 15:13:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Clear_the_context_flags_if_?= =?utf8?q?a_context_is_initialized_from_the_DefaultContext=2E?= Message-ID: http://hg.python.org/cpython/rev/2345a042c08a changeset: 76063:2345a042c08a parent: 76055:1f5701ffa077 user: Stefan Krah date: Mon Apr 02 15:02:21 2012 +0200 summary: Clear the context flags if a context is initialized from the DefaultContext. files: Lib/test/test_decimal.py | 70 +++++++++++++++++++++++++ Modules/_decimal/_decimal.c | 8 ++ 2 files changed, 78 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -56,6 +56,76 @@ fractions = {C:cfractions, P:pfractions} sys.modules['decimal'] = orig_sys_decimal +############ RunFirst ############ +class RunFirst(unittest.TestCase): + + def setUp(self): + self.save_default = self.decimal.DefaultContext.copy() + + def tearDown(self): + DefaultContext = self.decimal.DefaultContext + + DefaultContext.prec = self.save_default.prec + DefaultContext.rounding = self.save_default.rounding + DefaultContext.Emax = self.save_default.Emax + DefaultContext.Emin = self.save_default.Emin + DefaultContext.capitals = self.save_default.capitals + DefaultContext.clamp = self.save_default.clamp + DefaultContext.flags = self.save_default.flags + DefaultContext.traps = self.save_default.traps + + self.decimal.setcontext(self.decimal.DefaultContext) + + def test_00default_context(self): + # The test depends on the fact that getcontext() is called + # for the first time. + DefaultContext = self.decimal.DefaultContext + ROUND_05UP = self.decimal.ROUND_05UP + Clamped = self.decimal.Clamped + InvalidOperation = self.decimal.InvalidOperation + + DefaultContext.prec = 5001 + DefaultContext.rounding = ROUND_05UP + DefaultContext.Emax = 10025 + DefaultContext.Emin = -10025 + DefaultContext.capitals = 0 + DefaultContext.clamp = 1 + DefaultContext.flags[InvalidOperation] = True + DefaultContext.clear_traps() + DefaultContext.traps[Clamped] = True + + # implicit initialization on first access + c = self.decimal.getcontext() + + self.assertEqual(c.prec, 5001) + self.assertEqual(c.rounding, ROUND_05UP) + self.assertEqual(c.Emax, 10025) + self.assertEqual(c.Emin, -10025) + self.assertEqual(c.capitals, 0) + self.assertEqual(c.clamp, 1) + for k in c.flags: + self.assertFalse(c.flags[k]) + for k in c.traps: + if k is Clamped: + self.assertTrue(c.traps[k]) + else: + self.assertFalse(c.traps[k]) + + # explicit initialization + self.decimal.setcontext(DefaultContext) + c = self.decimal.getcontext() + for k in c.flags: + self.assertFalse(c.flags[k]) + +class CRunFirst(RunFirst): + decimal = C +class PyRunFirst(RunFirst): + decimal = P +if C: + run_unittest(CRunFirst, PyRunFirst) +else: + run_unittest(PyRunFirst) +############ END RunFirst ############ # Useful Test Constant Signals = { diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1494,6 +1494,10 @@ } *CTX(module_context) = *CTX(default_context_template); + CTX(module_context)->status = 0; + CTX(module_context)->newtrap = 0; + CtxCaps(module_context) = CtxCaps(default_context_template); + module_context_set = 1; return module_context; } @@ -1533,6 +1537,7 @@ if (v == NULL) { return NULL; } + CTX(v)->status = 0; } else { Py_INCREF(v); @@ -1581,6 +1586,8 @@ if (tl_context == NULL) { return NULL; } + CTX(tl_context)->status = 0; + if (PyDict_SetItem(dict, tls_context_key, tl_context) < 0) { Py_DECREF(tl_context); return NULL; @@ -1646,6 +1653,7 @@ if (v == NULL) { return NULL; } + CTX(v)->status = 0; } else { Py_INCREF(v); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 15:13:19 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 02 Apr 2012 15:13:19 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?b?KTogTWVyZ2Uu?= Message-ID: http://hg.python.org/cpython/rev/f00fae41f95d changeset: 76064:f00fae41f95d parent: 76063:2345a042c08a parent: 76062:9fcb2676696c user: Stefan Krah date: Mon Apr 02 15:04:14 2012 +0200 summary: Merge. files: Include/patchlevel.h | 2 +- Misc/NEWS | 64 +++++++++++++++++++------------- Objects/typeobject.c | 22 ++++------ 3 files changed, 48 insertions(+), 40 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.3.0a2" +#define PY_VERSION "3.3.0a2+" /*--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,10 +2,10 @@ Python News +++++++++++ -What's New in Python 3.3.0 Alpha 2? +What's New in Python 3.3.0 Alpha 3? =================================== -*Release date: 01-Apr-2012* +*Release date: XXXX-XX-XX* Core and Builtins ----------------- @@ -13,30 +13,6 @@ - Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch by Suman Saha. -- Issue #1683368: object.__new__ and object.__init__ raise a TypeError if they - are passed arguments and their complementary method is not overridden. - -- Issue #14378: Fix compiling ast.ImportFrom nodes with a "__future__" string as - the module name that was not interned. - -- Issue #14331: Use significantly less stack space when importing modules by - allocating path buffers on the heap instead of the stack. - -- Issue #14334: Prevent in a segfault in type.__getattribute__ when it was not - passed strings. - -- Issue #1469629: Allow cycles through an object's __dict__ slot to be - collected. (For example if ``x.__dict__ is x``). - -- Issue #14205: dict lookup raises a RuntimeError if the dict is modified - during a lookup. - -- Issue #14220: When a generator is delegating to another iterator with the - yield from syntax, it needs to have its ``gi_running`` flag set to True. - -- Issue #14435: Remove dedicated block allocator from floatobject.c and rely - on the PyObject_Malloc() api like all other objects. - Library ------- @@ -44,6 +20,42 @@ a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. + +What's New in Python 3.3.0 Alpha 2? +=================================== + +*Release date: 01-Apr-2012* + +Core and Builtins +----------------- + +- Issue #1683368: object.__new__ and object.__init__ raise a TypeError if they + are passed arguments and their complementary method is not overridden. + +- Issue #14378: Fix compiling ast.ImportFrom nodes with a "__future__" string as + the module name that was not interned. + +- Issue #14331: Use significantly less stack space when importing modules by + allocating path buffers on the heap instead of the stack. + +- Issue #14334: Prevent in a segfault in type.__getattribute__ when it was not + passed strings. + +- Issue #1469629: Allow cycles through an object's __dict__ slot to be + collected. (For example if ``x.__dict__ is x``). + +- Issue #14205: dict lookup raises a RuntimeError if the dict is modified + during a lookup. + +- Issue #14220: When a generator is delegating to another iterator with the + yield from syntax, it needs to have its ``gi_running`` flag set to True. + +- Issue #14435: Remove dedicated block allocator from floatobject.c and rely + on the PyObject_Malloc() api like all other objects. + +Library +------- + - Issue #14300: Under Windows, sockets created using socket.dup() now allow overlapped I/O. Patch by sbt. diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -490,26 +490,22 @@ for (i = 0; i < PyTuple_GET_SIZE(value); i++) { ob = PyTuple_GET_ITEM(value, i); if (!PyType_Check(ob)) { - PyErr_Format( - PyExc_TypeError, - "%s.__bases__ must be tuple of classes, not '%s'", - type->tp_name, Py_TYPE(ob)->tp_name); - return -1; + PyErr_Format(PyExc_TypeError, + "%s.__bases__ must be tuple of classes, not '%s'", + type->tp_name, Py_TYPE(ob)->tp_name); + return -1; } - if (PyType_Check(ob)) { - if (PyType_IsSubtype((PyTypeObject*)ob, type)) { - PyErr_SetString(PyExc_TypeError, - "a __bases__ item causes an inheritance cycle"); - return -1; - } + if (PyType_IsSubtype((PyTypeObject*)ob, type)) { + PyErr_SetString(PyExc_TypeError, + "a __bases__ item causes an inheritance cycle"); + return -1; } } new_base = best_base(value); - if (!new_base) { + if (!new_base) return -1; - } if (!compatible_for_assignment(type->tp_base, new_base, "__bases__")) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 15:13:19 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 02 Apr 2012 15:13:19 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Whitespace=2E?= Message-ID: http://hg.python.org/cpython/rev/883689757a2e changeset: 76065:883689757a2e user: Stefan Krah date: Mon Apr 02 15:10:36 2012 +0200 summary: Whitespace. files: Lib/test/test_decimal.py | 114 +++++++++++++------------- 1 files changed, 57 insertions(+), 57 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -59,63 +59,63 @@ ############ RunFirst ############ class RunFirst(unittest.TestCase): - def setUp(self): - self.save_default = self.decimal.DefaultContext.copy() - - def tearDown(self): - DefaultContext = self.decimal.DefaultContext - - DefaultContext.prec = self.save_default.prec - DefaultContext.rounding = self.save_default.rounding - DefaultContext.Emax = self.save_default.Emax - DefaultContext.Emin = self.save_default.Emin - DefaultContext.capitals = self.save_default.capitals - DefaultContext.clamp = self.save_default.clamp - DefaultContext.flags = self.save_default.flags - DefaultContext.traps = self.save_default.traps - - self.decimal.setcontext(self.decimal.DefaultContext) - - def test_00default_context(self): - # The test depends on the fact that getcontext() is called - # for the first time. - DefaultContext = self.decimal.DefaultContext - ROUND_05UP = self.decimal.ROUND_05UP - Clamped = self.decimal.Clamped - InvalidOperation = self.decimal.InvalidOperation - - DefaultContext.prec = 5001 - DefaultContext.rounding = ROUND_05UP - DefaultContext.Emax = 10025 - DefaultContext.Emin = -10025 - DefaultContext.capitals = 0 - DefaultContext.clamp = 1 - DefaultContext.flags[InvalidOperation] = True - DefaultContext.clear_traps() - DefaultContext.traps[Clamped] = True - - # implicit initialization on first access - c = self.decimal.getcontext() - - self.assertEqual(c.prec, 5001) - self.assertEqual(c.rounding, ROUND_05UP) - self.assertEqual(c.Emax, 10025) - self.assertEqual(c.Emin, -10025) - self.assertEqual(c.capitals, 0) - self.assertEqual(c.clamp, 1) - for k in c.flags: - self.assertFalse(c.flags[k]) - for k in c.traps: - if k is Clamped: - self.assertTrue(c.traps[k]) - else: - self.assertFalse(c.traps[k]) - - # explicit initialization - self.decimal.setcontext(DefaultContext) - c = self.decimal.getcontext() - for k in c.flags: - self.assertFalse(c.flags[k]) + def setUp(self): + self.save_default = self.decimal.DefaultContext.copy() + + def tearDown(self): + DefaultContext = self.decimal.DefaultContext + + DefaultContext.prec = self.save_default.prec + DefaultContext.rounding = self.save_default.rounding + DefaultContext.Emax = self.save_default.Emax + DefaultContext.Emin = self.save_default.Emin + DefaultContext.capitals = self.save_default.capitals + DefaultContext.clamp = self.save_default.clamp + DefaultContext.flags = self.save_default.flags + DefaultContext.traps = self.save_default.traps + + self.decimal.setcontext(self.decimal.DefaultContext) + + def test_00default_context(self): + # The test depends on the fact that getcontext() is called + # for the first time. + DefaultContext = self.decimal.DefaultContext + ROUND_05UP = self.decimal.ROUND_05UP + Clamped = self.decimal.Clamped + InvalidOperation = self.decimal.InvalidOperation + + DefaultContext.prec = 5001 + DefaultContext.rounding = ROUND_05UP + DefaultContext.Emax = 10025 + DefaultContext.Emin = -10025 + DefaultContext.capitals = 0 + DefaultContext.clamp = 1 + DefaultContext.flags[InvalidOperation] = True + DefaultContext.clear_traps() + DefaultContext.traps[Clamped] = True + + # implicit initialization on first access + c = self.decimal.getcontext() + + self.assertEqual(c.prec, 5001) + self.assertEqual(c.rounding, ROUND_05UP) + self.assertEqual(c.Emax, 10025) + self.assertEqual(c.Emin, -10025) + self.assertEqual(c.capitals, 0) + self.assertEqual(c.clamp, 1) + for k in c.flags: + self.assertFalse(c.flags[k]) + for k in c.traps: + if k is Clamped: + self.assertTrue(c.traps[k]) + else: + self.assertFalse(c.traps[k]) + + # explicit initialization + self.decimal.setcontext(DefaultContext) + c = self.decimal.getcontext() + for k in c.flags: + self.assertFalse(c.flags[k]) class CRunFirst(RunFirst): decimal = C -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 17:15:24 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 17:15:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_prevent_writing?= =?utf8?q?_to_stderr_from_messing_up_the_exception_state_=28closes_=231447?= =?utf8?q?4=29?= Message-ID: http://hg.python.org/cpython/rev/8609d7fcdcc7 changeset: 76066:8609d7fcdcc7 branch: 2.7 parent: 76049:d3a82a26c705 user: Benjamin Peterson date: Mon Apr 02 11:15:17 2012 -0400 summary: prevent writing to stderr from messing up the exception state (closes #14474) files: Lib/test/test_thread.py | 24 ++++++++++++++++++++++++ Misc/NEWS | 3 +++ Modules/threadmodule.c | 3 +++ 3 files changed, 30 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -130,6 +130,30 @@ time.sleep(0.01) self.assertEqual(thread._count(), orig) + def test_save_exception_state_on_error(self): + # See issue #14474 + def task(): + started.release() + sys.stderr = stderr + raise SyntaxError + def mywrite(self, *args): + try: + raise ValueError + except ValueError: + pass + real_write(self, *args) + c = thread._count() + started = thread.allocate_lock() + with test_support.captured_output("stderr") as stderr: + real_write = stderr.write + stderr.write = mywrite + started.acquire() + thread.start_new_thread(task, ()) + started.acquire() + while thread._count() > c: + pass + self.assertIn("Traceback", stderr.getvalue()) + class Barrier: def __init__(self, num_threads): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ Core and Builtins ----------------- +- Issue #14474: Save and restore exception state in thread.start_new_thread() + while writing error message if the thread leaves a unhandled exception. + - Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch by Suman Saha. diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c --- a/Modules/threadmodule.c +++ b/Modules/threadmodule.c @@ -618,6 +618,8 @@ PyErr_Clear(); else { PyObject *file; + PyObject *exc, *value, *tb; + PyErr_Fetch(&exc, &value, &tb); PySys_WriteStderr( "Unhandled exception in thread started by "); file = PySys_GetObject("stderr"); @@ -625,6 +627,7 @@ PyFile_WriteObject(boot->func, file, 0); else PyObject_Print(boot->func, stderr, 0); + PyErr_Restore(exc, value, tb); PySys_WriteStderr("\n"); PyErr_PrintEx(0); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 17:20:05 2012 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 2 Apr 2012 17:20:05 +0200 (CEST) Subject: [Python-checkins] r88934 - tracker/instances/spambayes_integration/extensions/spambayes.py Message-ID: <3VLxv91LfQzLrZ@mail.python.org> Author: martin.v.loewis Date: Mon Apr 2 17:20:04 2012 New Revision: 88934 Log: Issue 409: support spam classification without spambayes. Modified: tracker/instances/spambayes_integration/extensions/spambayes.py Modified: tracker/instances/spambayes_integration/extensions/spambayes.py ============================================================================== --- tracker/instances/spambayes_integration/extensions/spambayes.py (original) +++ tracker/instances/spambayes_integration/extensions/spambayes.py Mon Apr 2 17:20:04 2012 @@ -24,6 +24,9 @@ return (content, tokens) def train_spambayes(db, content, tokens, is_spam): + # spambayes training is now disabled; only leave + # spam classification UI + return True, None spambayes_uri = db.config.detectors['SPAMBAYES_URI'] server = xmlrpclib.ServerProxy(spambayes_uri, verbose=False) From python-checkins at python.org Mon Apr 2 17:28:55 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 17:28:55 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_protect_this_ca?= =?utf8?q?ll=2C_too?= Message-ID: http://hg.python.org/cpython/rev/d552016fc07c changeset: 76067:d552016fc07c branch: 2.7 user: Benjamin Peterson date: Mon Apr 02 11:18:18 2012 -0400 summary: protect this call, too files: Modules/threadmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c --- a/Modules/threadmodule.c +++ b/Modules/threadmodule.c @@ -627,8 +627,8 @@ PyFile_WriteObject(boot->func, file, 0); else PyObject_Print(boot->func, stderr, 0); + PySys_WriteStderr("\n"); PyErr_Restore(exc, value, tb); - PySys_WriteStderr("\n"); PyErr_PrintEx(0); } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 17:28:56 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 17:28:56 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_prevent_writing?= =?utf8?q?_to_stderr_from_messing_up_the_exception_state_=28closes_=231447?= =?utf8?q?4=29?= Message-ID: http://hg.python.org/cpython/rev/60ad83716733 changeset: 76068:60ad83716733 branch: 3.2 parent: 76059:d746ffc34e0f user: Benjamin Peterson date: Mon Apr 02 11:15:17 2012 -0400 summary: prevent writing to stderr from messing up the exception state (closes #14474) files: Lib/test/test_thread.py | 24 ++++++++++++++++++++++++ Misc/NEWS | 3 +++ Modules/_threadmodule.c | 3 +++ 3 files changed, 30 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -128,6 +128,30 @@ time.sleep(0.01) self.assertEqual(thread._count(), orig) + def test_save_exception_state_on_error(self): + # See issue #14474 + def task(): + started.release() + sys.stderr = stderr + raise SyntaxError + def mywrite(self, *args): + try: + raise ValueError + except ValueError: + pass + real_write(self, *args) + c = thread._count() + started = thread.allocate_lock() + with support.captured_output("stderr") as stderr: + real_write = stderr.write + stderr.write = mywrite + started.acquire() + thread.start_new_thread(task, ()) + started.acquire() + while thread._count() > c: + pass + self.assertIn("Traceback", stderr.getvalue()) + class Barrier: def __init__(self, num_threads): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14474: Save and restore exception state in thread.start_new_thread() + while writing error message if the thread leaves a unhandled exception. + - Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch by Suman Saha. diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -994,14 +994,17 @@ PyErr_Clear(); else { PyObject *file; + PyObject *exc, *value, *tb; PySys_WriteStderr( "Unhandled exception in thread started by "); + PyErr_Fetch(&exc, &value, &tb); file = PySys_GetObject("stderr"); if (file != NULL && file != Py_None) PyFile_WriteObject(boot->func, file, 0); else PyObject_Print(boot->func, stderr, 0); PySys_WriteStderr("\n"); + PyErr_Restore(exc, value, tb); PyErr_PrintEx(0); } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 17:28:58 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 17:28:58 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/b92e34c1e07c changeset: 76069:b92e34c1e07c parent: 76065:883689757a2e parent: 76068:60ad83716733 user: Benjamin Peterson date: Mon Apr 02 11:28:49 2012 -0400 summary: merge 3.2 files: Lib/test/test_thread.py | 24 ++++++++++++++++++++++++ Misc/NEWS | 3 +++ Modules/_threadmodule.c | 3 +++ 3 files changed, 30 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -128,6 +128,30 @@ time.sleep(0.01) self.assertEqual(thread._count(), orig) + def test_save_exception_state_on_error(self): + # See issue #14474 + def task(): + started.release() + sys.stderr = stderr + raise SyntaxError + def mywrite(self, *args): + try: + raise ValueError + except ValueError: + pass + real_write(self, *args) + c = thread._count() + started = thread.allocate_lock() + with support.captured_output("stderr") as stderr: + real_write = stderr.write + stderr.write = mywrite + started.acquire() + thread.start_new_thread(task, ()) + started.acquire() + while thread._count() > c: + pass + self.assertIn("Traceback", stderr.getvalue()) + class Barrier: def __init__(self, num_threads): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14474: Save and restore exception state in thread.start_new_thread() + while writing error message if the thread leaves a unhandled exception. + - Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch by Suman Saha. diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1001,14 +1001,17 @@ PyErr_Clear(); else { PyObject *file; + PyObject *exc, *value, *tb; PySys_WriteStderr( "Unhandled exception in thread started by "); + PyErr_Fetch(&exc, &value, &tb); file = PySys_GetObject("stderr"); if (file != NULL && file != Py_None) PyFile_WriteObject(boot->func, file, 0); else PyObject_Print(boot->func, stderr, 0); PySys_WriteStderr("\n"); + PyErr_Restore(exc, value, tb); PyErr_PrintEx(0); } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 17:41:33 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Mon, 02 Apr 2012 17:41:33 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NDcx?= =?utf8?q?=3A_Fix_a_possible_buffer_overrun_in_the_winreg_module=2E?= Message-ID: http://hg.python.org/cpython/rev/b3639f6aaa2b changeset: 76070:b3639f6aaa2b branch: 3.2 parent: 76068:60ad83716733 user: Kristj?n Valur J?nsson date: Mon Apr 02 15:23:29 2012 +0000 summary: Issue #14471: Fix a possible buffer overrun in the winreg module. files: Misc/NEWS | 2 ++ PC/winreg.c | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ - Issue #13521: dict.setdefault() now does only one lookup for the given key, making it "atomic" for many purposes. Patch by Filip Gruszczy?ski. +- Issue #14471: Fix a possible buffer overrun in the winreg module. + Library ------- diff --git a/PC/winreg.c b/PC/winreg.c --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1110,7 +1110,7 @@ * nul. RegEnumKeyEx requires a 257 character buffer to * retrieve such a key name. */ wchar_t tmpbuf[257]; - DWORD len = sizeof(tmpbuf); /* includes NULL terminator */ + DWORD len = sizeof(tmpbuf)/sizeof(wchar_t); /* includes NULL terminator */ if (!PyArg_ParseTuple(args, "Oi:EnumKey", &obKey, &index)) return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 17:41:34 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Mon, 02 Apr 2012 17:41:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_with_3=2E2_=28Issue_=2314471=29?= Message-ID: http://hg.python.org/cpython/rev/80d814d7b886 changeset: 76071:80d814d7b886 parent: 76069:b92e34c1e07c parent: 76070:b3639f6aaa2b user: Kristj?n Valur J?nsson date: Mon Apr 02 15:41:06 2012 +0000 summary: Merge with 3.2 (Issue #14471) files: Misc/NEWS | 2 ++ PC/winreg.c | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,8 @@ - Issue #14435: Remove dedicated block allocator from floatobject.c and rely on the PyObject_Malloc() api like all other objects. +- Issue #14471: Fix a possible buffer overrun in the winreg module. + Library ------- diff --git a/PC/winreg.c b/PC/winreg.c --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1122,7 +1122,7 @@ * nul. RegEnumKeyEx requires a 257 character buffer to * retrieve such a key name. */ wchar_t tmpbuf[257]; - DWORD len = sizeof(tmpbuf); /* includes NULL terminator */ + DWORD len = sizeof(tmpbuf)/sizeof(wchar_t); /* includes NULL terminator */ if (!PyArg_ParseTuple(args, "Oi:EnumKey", &obKey, &index)) return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 18:18:08 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 02 Apr 2012 18:18:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Guard_an_LLTRACE_variable_t?= =?utf8?q?o_silence_an_unused_variable_warning=2E?= Message-ID: http://hg.python.org/cpython/rev/bac033e488b4 changeset: 76072:bac033e488b4 user: Brett Cannon date: Mon Apr 02 12:17:59 2012 -0400 summary: Guard an LLTRACE variable to silence an unused variable warning. files: Python/ceval.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -822,7 +822,9 @@ PyObject *names; PyObject *consts; +#ifdef LLTRACE _Py_IDENTIFIER(__ltrace__); +#endif /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 19:11:58 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 02 Apr 2012 19:11:58 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Testing_the_implicit_initia?= =?utf8?q?lization_of_the_thread_local_context_on_first?= Message-ID: http://hg.python.org/cpython/rev/09cff57b5541 changeset: 76073:09cff57b5541 user: Stefan Krah date: Mon Apr 02 19:10:20 2012 +0200 summary: Testing the implicit initialization of the thread local context on first access fails (expectedly) if other modules have already used decimal. The only option is to remove the test. files: Lib/test/test_decimal.py | 70 ---------------------------- 1 files changed, 0 insertions(+), 70 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -56,76 +56,6 @@ fractions = {C:cfractions, P:pfractions} sys.modules['decimal'] = orig_sys_decimal -############ RunFirst ############ -class RunFirst(unittest.TestCase): - - def setUp(self): - self.save_default = self.decimal.DefaultContext.copy() - - def tearDown(self): - DefaultContext = self.decimal.DefaultContext - - DefaultContext.prec = self.save_default.prec - DefaultContext.rounding = self.save_default.rounding - DefaultContext.Emax = self.save_default.Emax - DefaultContext.Emin = self.save_default.Emin - DefaultContext.capitals = self.save_default.capitals - DefaultContext.clamp = self.save_default.clamp - DefaultContext.flags = self.save_default.flags - DefaultContext.traps = self.save_default.traps - - self.decimal.setcontext(self.decimal.DefaultContext) - - def test_00default_context(self): - # The test depends on the fact that getcontext() is called - # for the first time. - DefaultContext = self.decimal.DefaultContext - ROUND_05UP = self.decimal.ROUND_05UP - Clamped = self.decimal.Clamped - InvalidOperation = self.decimal.InvalidOperation - - DefaultContext.prec = 5001 - DefaultContext.rounding = ROUND_05UP - DefaultContext.Emax = 10025 - DefaultContext.Emin = -10025 - DefaultContext.capitals = 0 - DefaultContext.clamp = 1 - DefaultContext.flags[InvalidOperation] = True - DefaultContext.clear_traps() - DefaultContext.traps[Clamped] = True - - # implicit initialization on first access - c = self.decimal.getcontext() - - self.assertEqual(c.prec, 5001) - self.assertEqual(c.rounding, ROUND_05UP) - self.assertEqual(c.Emax, 10025) - self.assertEqual(c.Emin, -10025) - self.assertEqual(c.capitals, 0) - self.assertEqual(c.clamp, 1) - for k in c.flags: - self.assertFalse(c.flags[k]) - for k in c.traps: - if k is Clamped: - self.assertTrue(c.traps[k]) - else: - self.assertFalse(c.traps[k]) - - # explicit initialization - self.decimal.setcontext(DefaultContext) - c = self.decimal.getcontext() - for k in c.flags: - self.assertFalse(c.flags[k]) - -class CRunFirst(RunFirst): - decimal = C -class PyRunFirst(RunFirst): - decimal = P -if C: - run_unittest(CRunFirst, PyRunFirst) -else: - run_unittest(PyRunFirst) -############ END RunFirst ############ # Useful Test Constant Signals = { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 20:26:00 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 20:26:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_remove_uneeded_?= =?utf8?q?line?= Message-ID: http://hg.python.org/cpython/rev/2b7aff01ca89 changeset: 76074:2b7aff01ca89 branch: 2.7 parent: 76067:d552016fc07c user: Benjamin Peterson date: Mon Apr 02 14:22:50 2012 -0400 summary: remove uneeded line files: Lib/test/test_thread.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -134,7 +134,6 @@ # See issue #14474 def task(): started.release() - sys.stderr = stderr raise SyntaxError def mywrite(self, *args): try: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 20:26:01 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 20:26:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_remove_uneeded_?= =?utf8?q?line?= Message-ID: http://hg.python.org/cpython/rev/98ab6e322c40 changeset: 76075:98ab6e322c40 branch: 3.2 parent: 76070:b3639f6aaa2b user: Benjamin Peterson date: Mon Apr 02 14:22:50 2012 -0400 summary: remove uneeded line files: Lib/test/test_thread.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -132,7 +132,6 @@ # See issue #14474 def task(): started.release() - sys.stderr = stderr raise SyntaxError def mywrite(self, *args): try: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 20:26:03 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 02 Apr 2012 20:26:03 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/e97940f701be changeset: 76076:e97940f701be parent: 76073:09cff57b5541 parent: 76075:98ab6e322c40 user: Benjamin Peterson date: Mon Apr 02 14:25:55 2012 -0400 summary: merge 3.2 files: Lib/test/test_thread.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -132,7 +132,6 @@ # See issue #14474 def task(): started.release() - sys.stderr = stderr raise SyntaxError def mywrite(self, *args): try: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 21:00:32 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 02 Apr 2012 21:00:32 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Improve_comments=2E?= Message-ID: http://hg.python.org/cpython/rev/5fe882b2e00f changeset: 76077:5fe882b2e00f parent: 76073:09cff57b5541 user: Stefan Krah date: Mon Apr 02 20:51:08 2012 +0200 summary: Improve comments. files: Modules/_decimal/_decimal.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1510,7 +1510,7 @@ #define CURRENT_CONTEXT_ADDR(ctx) \ ctx = CTX(current_context()) -/* Return current context, increment reference */ +/* Return a new reference to the current context */ static PyObject * PyDec_GetCurrentContext(void) { @@ -1614,7 +1614,7 @@ ctx = CTX(_c_t_x_o_b_j); \ } -/* Return current context, increment reference */ +/* Return a new reference to the current context */ static PyObject * PyDec_GetCurrentContext(void) { @@ -1759,7 +1759,7 @@ 0, /* tp_print */ (getattrfunc) 0, /* tp_getattr */ (setattrfunc) 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc) 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -2699,7 +2699,7 @@ /******************************************************************************/ -/* Implicit conversions to Decimal */ +/* Implicit conversions to Decimal */ /******************************************************************************/ /* Try to convert PyObject v to a new PyDecObject conv. If the conversion @@ -2796,7 +2796,7 @@ /******************************************************************************/ -/* Implicit conversions to Decimal for comparison */ +/* Implicit conversions to Decimal for comparison */ /******************************************************************************/ /* Convert rationals for comparison */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 21:00:33 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 02 Apr 2012 21:00:33 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?b?KTogTWVyZ2Uu?= Message-ID: http://hg.python.org/cpython/rev/44c6997191d3 changeset: 76078:44c6997191d3 parent: 76077:5fe882b2e00f parent: 76076:e97940f701be user: Stefan Krah date: Mon Apr 02 20:59:15 2012 +0200 summary: Merge. files: Lib/test/test_thread.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -132,7 +132,6 @@ # See issue #14474 def task(): started.release() - sys.stderr = stderr raise SyntaxError def mywrite(self, *args): try: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 2 21:48:06 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 02 Apr 2012 21:48:06 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_time=2Eget=5Fclock?= =?utf8?q?=5Finfo=28=29_may_provide_more_information_=28accuracy=2C?= Message-ID: http://hg.python.org/peps/rev/aeff04d14ad8 changeset: 4186:aeff04d14ad8 user: Victor Stinner date: Mon Apr 02 21:48:03 2012 +0200 summary: PEP 418: time.get_clock_info() may provide more information (accuracy, is_adjusted) files: pep-0418.txt | 21 ++++++++++++++------- 1 files changed, 14 insertions(+), 7 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -201,20 +201,27 @@ time.get_clock_info(name) ------------------------- -Get information on the specified time function as a dictionary. Only the following -names are accepted: +Get information on the specified clock. Supported clocks: * "clock": time.clock() * "highres": time.highres() * "monotonic": time.monotonic() * "time": time.time() -The following keys are always present: +Return a dictionary with the following keys: - * "function" (str): name of the underlying operating system function (ex: - "QueryPerformanceCounter()" or "clock_gettime(CLOCK_REALTIME)") - * "resolution" (float): resolution in seconds of the function - * "is_monotonic" (bool): True if the clock is monotonic + * Mandatory keys: + + * "function" (str): name of the underlying operating system function. + Examples: "QueryPerformanceCounter()", "clock_gettime(CLOCK_REALTIME)". + * "resolution" (float): resolution in seconds of the clock + * "is_monotonic" (bool): True if the clock cannot go backward + + * Optional keys: + + * "accuracy" (float): accuracy in seconds of the clock + * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a NTP + daemon) Hardware clocks -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 2 21:52:40 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 02 Apr 2012 21:52:40 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_link_to_libpthr?= =?utf8?q?ead_for_Windows?= Message-ID: http://hg.python.org/peps/rev/13cf90c1c02b changeset: 4187:13cf90c1c02b user: Victor Stinner date: Mon Apr 02 21:52:32 2012 +0200 summary: PEP 418: Add link to libpthread for Windows files: pep-0418.txt | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -764,6 +764,9 @@ clock_gettime(CLOCK_MONOTONIC), mach_absolute_time() or gettimeofday(). "AbsoluteTime.monotonic?" method indicates if AbsoluteTime.now is monotonic or not. +* `libpthread + `_: POSIX thread library for Windows + (`clock.c `_) Time: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 3 00:18:54 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 03 Apr 2012 00:18:54 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_tables_of_clock?= =?utf8?q?_accuracy?= Message-ID: http://hg.python.org/peps/rev/8fbc2d2213b9 changeset: 4188:8fbc2d2213b9 user: Victor Stinner date: Tue Apr 03 00:18:51 2012 +0200 summary: PEP 418: Add tables of clock accuracy * Add a "NTP adjusted" section * Don't use CLOCK_MONOTONIC_RAW on Linux for time.monotonic() files: pep-0418.txt | 95 ++++++++++++++++++++++++++++++++++----- 1 files changed, 82 insertions(+), 13 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -143,12 +143,9 @@ clk_id = monotonic.clocks[0] return time.clock_gettime(clk_id) except OSError: - # CLOCK_MONOTONIC_RAW requires a Linux kernel >= 2.6.28 del monotonic.clocks[0] return time.time() monotonic.clocks = [] - if hasattr(time, 'CLOCK_MONOTONIC_RAW'): - monotonic.clocks.append(time.CLOCK_MONOTONIC_RAW) if hasattr(time, 'CLOCK_HIGHRES'): monotonic.clocks.append(time.CLOCK_HIGHRES) monotonic.clocks.append(time.CLOCK_MONOTONIC) @@ -246,6 +243,32 @@ 32,768 Hz +NTP adjusted +============ + +NTP has diffent methods to adjust a clock: + + * "slewing": change the clock frequency to be slightly faster or slower + (which is done with adjtime()). Since the slew rate is limited to 0.5 ms/s, + each second of adjustment requires an amortization interval of 2000 s. Thus, + an adjustment of many seconds can take hours or days to amortize. + * "stepping": jump by a large amount in a single discrete step (which is done + with settimeofday()) + +By default, the time is slewed if the offset is less than 128 ms, or stepped +otherwise. + +Slewing is generally desirable (i.e. we should use CLOCK_MONOTONIC, not +CLOCK_MONOTONIC_RAW) if one wishes to measure "real" time (and not a time-like +object like CPU cycles). This is because the clock on the other end of the NTP +connection from you is probably better at keeping time: hopefully that thirty +five thousand dollars of Cesium timekeeping goodness is doing something better +than your PC's $3 quartz crystal, after all. + +Get more detail in the `documentation of the NTP daemon +`_. + + Operating system clocks ======================= @@ -258,7 +281,7 @@ CLOCK_MONOTONIC_RAW 1 ns (*) No Stopped gethrtime 1 ns (*) No Not stopped CLOCK_HIGHRES 1 ns (*) No ? -CLOCK_MONOTONIC 1 ns (*) Yes on Linux Stopped on Linux +CLOCK_MONOTONIC 1 ns (*) Slewed on Linux Stopped on Linux mach_absolute_time() 1 ns (*) No ? QueryPerformanceCounter() \- 0.3 ns - 5 ns No Accuracy issue GetTickCount[64]() 1 ms 1 ms - 15 ms No Include suspend time @@ -278,6 +301,25 @@ example, QueryPerformanceCounter() has a good accuracy but is known to not have a steady rate. +Examples of clock accuracy on x86_64: + +========================= ================ =============== +Name Operating system Accuracy +========================= ================ =============== +CLOCK_MONOTONIC_RAW Linux 3.2 1 ns +CLOCK_MONOTONIC Linux 3.2 1 ns +CLOCK_HIGHRES SunOS 5.11 2 ns +CLOCK_MONOTONIC SunOS 5.11 2 ns +QueryPerformanceCounter Windows Vista 10 ns +CLOCK_MONOTONIC FreeBSD 8.2 11 ns +CLOCK_MONOTONIC OpenBSD 5.0 10 ms +GetTickCount Windows Vista 15.6 ms +========================= ================ =============== + +For CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW, the accuracy of this table is the +result of clock_getres(). It looks like Linux does not implement +clock_getres() and always return 1 nanosecond. + mach_absolute_time ^^^^^^^^^^^^^^^^^^ @@ -325,14 +367,12 @@ * Mac OS X * Windows -CLOCK_MONOTONIC_RAW is specific to Linux. It is similar to -CLOCK_MONOTONIC, but provides access to a raw hardware-based time that -is not subject to NTP adjustments. CLOCK_MONOTONIC_RAW requires Linux -2.6.28 or later. +On Linux, NTP may adjust the CLOCK_MONOTONIC rate (slewed), but it cannot +jump backward. -On Linux, NTP may adjust the CLOCK_MONOTONIC rate, but it cannot jump -backward. If available, CLOCK_MONOTONIC_RAW should be used instead of -CLOCK_MONOTONIC to avoid the NTP adjustment. +CLOCK_MONOTONIC_RAW is specific to Linux. It is similar to CLOCK_MONOTONIC, but +provides access to a raw hardware-based time that is not subject to NTP +adjustments. CLOCK_MONOTONIC_RAW requires Linux 2.6.28 or later. CLOCK_MONOTONIC stops while the machine is suspended. @@ -504,8 +544,23 @@ ========================= =============== =============== (*) The accuracy of system clocks depends on the operating system and -the hardware clock. On Windows, the accuracy is in the range 1 ms - -15 ms. +the hardware clock. + +Examples of clock accuracy on x86_64: + +========================= ================ =============== +Name Operating system Accuracy +========================= ================ =============== +CLOCK_REALTIME Linux 3.2 1 ns +CLOCK_REALTIME FreeBSD 8.2 11 ns +CLOCK_REALTIME SunOS 5.11 10 ms +CLOCK_REALTIME OpenBSD 5.0 10 ms +GetSystemTimeAsFileTime Windows Vista 15.6 ms +========================= ================ =============== + +For CLOCK_REALTIME, the accuracy of this table is the result of clock_getres(). +It looks like Linux does not implement clock_getres() and always return 1 +nanosecond. Windows: GetSystemTimeAsFileTime @@ -573,6 +628,20 @@ clock_getres(CLOCK_REALTIME) is 1 nanosecond on Linux. * GetProcessTimes(): call GetSystemTimeAdjustment(). +Examples of clock accuracy on x86_64: + +========================= ================ =============== +Name Operating system Accuracy +========================= ================ =============== +clock() Linux 3.2 1 ms +clock() SunOS 5.11 1 ms +clock() FreeBSD 8.2 7.8 ms +clock() OpenBSD 5.0 10 ms +========================= ================ =============== + +The accuracy of clock() in this table is the result of 1 / CLOCKS_PER_SEC. + + Thread ^^^^^^ -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 3 00:31:22 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 03 Apr 2012 00:31:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Add_time=2ECLOCK=5FHIGHRES_?= =?utf8?q?constant=2C_needed_on_Solaris?= Message-ID: http://hg.python.org/cpython/rev/c5395ab7447a changeset: 76079:c5395ab7447a user: Victor Stinner date: Tue Apr 03 00:31:17 2012 +0200 summary: Add time.CLOCK_HIGHRES constant, needed on Solaris files: Doc/library/time.rst | 9 +++++++++ Modules/timemodule.c | 3 +++ 2 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -159,6 +159,15 @@ .. versionadded:: 3.3 +.. data:: CLOCK_HIGHRES + + The Solaris OS has a CLOCK_HIGHRES timer that attempts to use an optimal + hardware source, and may give close to nanosecond resolution. CLOCK_HIGHRES + is the nonadjustable, high-resolution clock. + + .. versionadded:: 3.3 + + .. data:: CLOCK_MONOTONIC Clock that cannot be set and represents monotonic time since some diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -962,6 +962,9 @@ #ifdef CLOCK_MONOTONIC_RAW PyModule_AddIntMacro(m, CLOCK_MONOTONIC_RAW); #endif +#ifdef CLOCK_HIGHRES + PyModule_AddIntMacro(m, CLOCK_HIGHRES); +#endif #ifdef CLOCK_PROCESS_CPUTIME_ID PyModule_AddIntMacro(m, CLOCK_PROCESS_CPUTIME_ID); #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 00:45:16 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 03 Apr 2012 00:45:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Expose_clock=5Fsettime=28?= =?utf8?q?=29_as_time=2Eclock=5Fsettime=28=29?= Message-ID: http://hg.python.org/cpython/rev/8ba72c0987dc changeset: 76080:8ba72c0987dc user: Victor Stinner date: Tue Apr 03 00:45:07 2012 +0200 summary: Expose clock_settime() as time.clock_settime() files: Doc/library/time.rst | 7 +++++++ Lib/test/test_time.py | 11 +++++++++++ Modules/timemodule.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 0 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -151,6 +151,13 @@ .. versionadded:: 3.3 +.. function:: clock_settime(clk_id, time) + + Set the time of the specified clock *clk_id*. + + .. versionadded:: 3.3 + + .. data:: CLOCK_REALTIME System-wide real-time clock. Setting this clock requires appropriate diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -47,6 +47,17 @@ self.assertGreater(res, 0.0) self.assertLessEqual(res, 1.0) + @unittest.skipUnless(hasattr(time, 'clock_settime'), + 'need time.clock_settime()') + def test_clock_settime(self): + t = time.clock_gettime(time.CLOCK_REALTIME) + try: + time.clock_settime(time.CLOCK_REALTIME, t) + except PermissionError: + pass + + self.assertRaises(OSError, time.clock_settime, time.CLOCK_MONOTONIC, 0) + def test_conversions(self): self.assertEqual(time.ctime(self.t), time.asctime(time.localtime(self.t))) diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -158,6 +158,33 @@ "clock_gettime(clk_id) -> floating point number\n\ \n\ Return the time of the specified clock clk_id."); + +static PyObject * +time_clock_settime(PyObject *self, PyObject *args) +{ + clockid_t clk_id; + PyObject *obj; + struct timespec tp; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) + return NULL; + + if (_PyTime_ObjectToTimespec(obj, &tp.tv_sec, &tp.tv_nsec) == -1) + return NULL; + + ret = clock_settime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(clock_settime_doc, +"clock_settime(clk_id, time)\n\ +\n\ +Set the time of the specified clock clk_id."); #endif #ifdef HAVE_CLOCK_GETRES @@ -983,6 +1010,9 @@ #ifdef HAVE_CLOCK_GETTIME {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, #endif +#ifdef HAVE_CLOCK_GETTIME + {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, +#endif #ifdef HAVE_CLOCK_GETRES {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 01:14:31 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 03 Apr 2012 01:14:31 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_the_accuracy_of?= =?utf8?q?_process_and_thread_time_clocks?= Message-ID: http://hg.python.org/peps/rev/c98fcd2b4631 changeset: 4189:c98fcd2b4631 user: Victor Stinner date: Tue Apr 03 01:14:28 2012 +0200 summary: PEP 418: Add the accuracy of process and thread time clocks files: pep-0418.txt | 146 ++++++++++++++++++++++++-------------- 1 files changed, 90 insertions(+), 56 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -275,21 +275,18 @@ Monotonic clocks ---------------- -========================= =============== =============== ================ ==================== -Name Resolution Accuracy Adjusted by NTP? Action on suspend -========================= =============== =============== ================ ==================== -CLOCK_MONOTONIC_RAW 1 ns (*) No Stopped -gethrtime 1 ns (*) No Not stopped -CLOCK_HIGHRES 1 ns (*) No ? -CLOCK_MONOTONIC 1 ns (*) Slewed on Linux Stopped on Linux -mach_absolute_time() 1 ns (*) No ? -QueryPerformanceCounter() \- 0.3 ns - 5 ns No Accuracy issue -GetTickCount[64]() 1 ms 1 ms - 15 ms No Include suspend time -timeGetTime() 1 ms 1 ms - 15 ms No ? -========================= =============== =============== ================ ==================== - -(*) The accuracy of monotonic clocks depends on the operating system -and the hardware clock. +========================= =============== ================ ==================== +Name Resolution Adjusted by NTP? Action on suspend +========================= =============== ================ ==================== +CLOCK_MONOTONIC_RAW 1 ns No Stopped +gethrtime 1 ns No Not stopped +CLOCK_HIGHRES 1 ns No ? +CLOCK_MONOTONIC 1 ns Slewed on Linux Stopped on Linux +mach_absolute_time() 1 ns No ? +QueryPerformanceCounter() \- No Accuracy issue +GetTickCount[64]() 1 ms No Include suspend time +timeGetTime() 1 ms No ? +========================= =============== ================ ==================== The resolution is the smallest difference between two timestamps supported by the format used by the clock. For example, @@ -306,14 +303,14 @@ ========================= ================ =============== Name Operating system Accuracy ========================= ================ =============== -CLOCK_MONOTONIC_RAW Linux 3.2 1 ns -CLOCK_MONOTONIC Linux 3.2 1 ns -CLOCK_HIGHRES SunOS 5.11 2 ns -CLOCK_MONOTONIC SunOS 5.11 2 ns -QueryPerformanceCounter Windows Vista 10 ns -CLOCK_MONOTONIC FreeBSD 8.2 11 ns -CLOCK_MONOTONIC OpenBSD 5.0 10 ms -GetTickCount Windows Vista 15.6 ms +CLOCK_MONOTONIC_RAW Linux 3.2 1 ns +CLOCK_MONOTONIC Linux 3.2 1 ns +CLOCK_HIGHRES SunOS 5.11 2 ns +CLOCK_MONOTONIC SunOS 5.11 2 ns +QueryPerformanceCounter Windows Seven 10 ns +CLOCK_MONOTONIC FreeBSD 8.2 11 ns +CLOCK_MONOTONIC OpenBSD 5.0 10 ms +GetTickCount Windows Seven 15.6 ms ========================= ================ =============== For CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW, the accuracy of this table is the @@ -533,18 +530,15 @@ System time clocks ------------------ -========================= =============== =============== -Name Resolution Accuracy -========================= =============== =============== -CLOCK_REALTIME 1 ns (*) -GetSystemTimeAsFileTime 100 ns 1 ms - 15 ms -gettimeofday() 1 ?s (*) -ftime() 1 ms (*) -time() 1 sec 1 sec -========================= =============== =============== - -(*) The accuracy of system clocks depends on the operating system and -the hardware clock. +========================= =============== +Name Resolution +========================= =============== +CLOCK_REALTIME 1 ns +GetSystemTimeAsFileTime 100 ns +gettimeofday() 1 ?s +ftime() 1 ms +time() 1 sec +========================= =============== Examples of clock accuracy on x86_64: @@ -555,7 +549,7 @@ CLOCK_REALTIME FreeBSD 8.2 11 ns CLOCK_REALTIME SunOS 5.11 10 ms CLOCK_REALTIME OpenBSD 5.0 10 ms -GetSystemTimeAsFileTime Windows Vista 15.6 ms +GetSystemTimeAsFileTime Windows Seven 15.6 ms ========================= ================ =============== For CLOCK_REALTIME, the accuracy of this table is the result of clock_getres(). @@ -587,7 +581,7 @@ Resolution: -* clock_gettime(): clock_getres(CLOCK_REALTIME), 1 nanosecond on Linux +* clock_gettime(): clock_getres(CLOCK_REALTIME) * gettimeofday(): 1 microsecond * ftime(): 1 millisecond * time(): 1 second @@ -596,14 +590,41 @@ clock_settime(CLOCK_REALTIME). -Process and thread time ------------------------ +Process time +------------ -The process and thread time cannot be set. They are not monotonic: -the clocks stop while the process/thread is idle. +The process time cannot be set. It is not monotonic: the clocks stop while the +process is idle. -Process -^^^^^^^ +========================= =============== +Name Resolution +========================= =============== +GetProcessTimes() 100 ns +CLOCK_PROCESS_CPUTIME_ID 1 ns +clock() \- +========================= =============== + +Examples of clock accuracy on x86_64: + +========================= ================ =============== +Name Operating system Accuracy +========================= ================ =============== +CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns +clock() Linux 3.2 1 ?s +clock() SunOS 5.11 1 ?s +clock() FreeBSD 8.2 7.8 ms +clock() OpenBSD 5.0 10 ms +GetProcessTimes() Windows Seven 15.6 ms +========================= ================ =============== + +The accuracy of clock() in this table is the result of 1 / CLOCKS_PER_SEC. +For CLOCK_PROCESS_CPUTIME_ID, the accuracy of this table is the result of +clock_getres(). It looks like Linux does not implement clock_getres() and +always return 1 nanosecond. For GetProcessTimes(), the accuracy is read using +GetSystemTimeAdjustment(). + +Functions +^^^^^^^^^ * Windows: GetProcessTimes() * clock_gettime(CLOCK_PROCESS_CPUTIME_ID): High-resolution per-process @@ -622,28 +643,41 @@ Resolution: * clock() rate is CLOCKS_PER_SEC. It was called CLK_TCK in Microsoft - C before 6.0. On Linux 3, clock() has a resolution of 1 - microsecond. + C before 6.0. * The clock resolution can be read using clock_getres(). - clock_getres(CLOCK_REALTIME) is 1 nanosecond on Linux. * GetProcessTimes(): call GetSystemTimeAdjustment(). + +Thread time +----------- + +The thread time cannot be set. It is not monotonic: the clocks stop while the +thread is idle. + +========================= =============== +Name Resolution +========================= =============== +GetThreadTimes() 100 ns +CLOCK_THREAD_CPUTIME_ID 1 ns +========================= =============== + Examples of clock accuracy on x86_64: ========================= ================ =============== Name Operating system Accuracy ========================= ================ =============== -clock() Linux 3.2 1 ms -clock() SunOS 5.11 1 ms -clock() FreeBSD 8.2 7.8 ms -clock() OpenBSD 5.0 10 ms +CLOCK_THREAD_CPUTIME_ID Linux 3.2 1 ns +CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s +GetThreadTimes() Windows Seven 15.6 ms ========================= ================ =============== -The accuracy of clock() in this table is the result of 1 / CLOCKS_PER_SEC. +For CLOCK_THREAD_CPUTIME_ID, the accuracy of this table is the result of +clock_getres(). It looks like Linux does not implement clock_getres() and +always return 1 nanosecond. For GetThreadTimes(), the accuracy is read using +GetSystemTimeAdjustment(). - -Thread -^^^^^^ +Functions +^^^^^^^^^ * Windows: GetThreadTimes() * clock_gettime(CLOCK_THREAD_CPUTIME_ID): Thread-specific CPU-time @@ -651,15 +685,14 @@ Resolution: -* CLOCK_THREAD_CPUTIME_ID: call clock_getres(). 1 nanosecond on - Linux. +* CLOCK_THREAD_CPUTIME_ID: call clock_getres(). * GetThreadTimes(): call GetSystemTimeAdjustment() See also pthread_getcpuclockid(). Windows: QueryUnbiasedInterruptTime -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +----------------------------------- Gets the current unbiased interrupt time from the biased interrupt time and the current sleep bias amount. This time is not affected by -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 3 01:26:38 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 03 Apr 2012 01:26:38 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_a_typo?= Message-ID: http://hg.python.org/peps/rev/3044ae06a38f changeset: 4190:3044ae06a38f user: Victor Stinner date: Tue Apr 03 01:26:35 2012 +0200 summary: PEP 418: Fix a typo files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -87,7 +87,7 @@ adjusted by NTP. The reference point of the returned value is undefined so only the difference of consecutive calls is valid. -Use time.get_clock_info('monotonic')['monotonic'] to check if the clock +Use time.get_clock_info('monotonic')['is_monotonic'] to check if the clock monotonic or not. The elapsed time may or may not include time the system spends in -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 3 01:42:46 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 03 Apr 2012 01:42:46 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Rename_time=2Emonot?= =?utf8?b?b25pYygpIHRvIHRpbWUuc3RlYWR5KCk=?= Message-ID: http://hg.python.org/peps/rev/9729fd8ba5b3 changeset: 4191:9729fd8ba5b3 user: Victor Stinner date: Tue Apr 03 01:42:42 2012 +0200 summary: PEP 418: Rename time.monotonic() to time.steady() files: pep-0418.txt | 98 ++++++++++++++++++++-------------------- 1 files changed, 49 insertions(+), 49 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1,5 +1,5 @@ PEP: 418 -Title: Add monotonic and high-resolution time functions +Title: Add steady and high-resolution time functions Version: $Revision$ Last-Modified: $Date$ Author: Victor Stinner @@ -13,7 +13,7 @@ Abstract ======== -Add time.monotonic(), time.highres(), time.get_clock_info(name) functions to +Add time.steady(), time.highres(), time.get_clock_info(name) functions to Python 3.3. @@ -26,7 +26,7 @@ a wall clock): use system clock, i.e. time.time() or datetime.datetime.now(). * Benchmark, profiling: time.highres(). -* Event scheduler, timeout: time.monotonic(). +* Event scheduler, timeout: time.steady(). Functions @@ -36,8 +36,7 @@ * time.time(): system clock, "wall clock". * time.highres(): clock with the best accuracy. -* time.monotonic(): monotonic clock, or system clock if no monotonic - clock is available +* time.steady(): steady clock, should be monotonic * time.get_clock_info(name): get information on the specified time function @@ -79,15 +78,14 @@ return _time.time() -time.monotonic() ----------------- +time.steady() +------------- -Monotonic clock, or system clock if the platform does not provide a monotonic -clock (e.g. on GNU/Hurd). Its rate is as steady as possible. Its rate may be -adjusted by NTP. The reference point of the returned value is undefined so -only the difference of consecutive calls is valid. +Steady clock. Use a monotonic clock, or falls back to the system clock. Its +rate may be adjusted by NTP. The reference point of the returned value is +undefined so only the difference of consecutive calls is valid. -Use time.get_clock_info('monotonic')['is_monotonic'] to check if the clock +Use time.get_clock_info('steady')['is_monotonic'] to check if the clock monotonic or not. The elapsed time may or may not include time the system spends in @@ -98,60 +96,60 @@ if os.name == 'nt': # GetTickCount64() requires Windows Vista, Server 2008 or later if hasattr(time, '_GetTickCount64'): - def monotonic(): + def steady(): return _time.GetTickCount64() else: - def monotonic(): + def steady(): ticks = _time.GetTickCount() - if ticks < monotonic.last: + if ticks < steady.last: # Integer overflow detected - monotonic.delta += 2**32 - monotonic.last = ticks - return ticks + monotonic.delta - monotonic.last = 0 - monotonic.delta = 0 + steady.delta += 2**32 + steady.last = ticks + return ticks + steady.delta + steady.last = 0 + steady.delta = 0 elif os.name == 'mac': - def monotonic(): - if monotonic.factor is None: + def steady(): + if steady.factor is None: factor = _time.mach_timebase_info() - monotonic.factor = timebase[0] / timebase[1] - return _time.mach_absolute_time() * monotonic.factor - monotonic.factor = None + steady.factor = timebase[0] / timebase[1] + return _time.mach_absolute_time() * steady.factor + steady.factor = None elif os.name.startswith('sunos'): - def monotonic(): - if monotonic.use_clock_highres: + def steady(): + if steady.use_clock_highres: try: time.clock_gettime(time.CLOCK_HIGHRES) except OSError: - monotonic.use_clock_highres = False - if monotonic.use_gethrtime: + steady.use_clock_highres = False + if steady.use_gethrtime: try: return time.gethrtime() except OSError: - monotonic.use_gethrtime = False + steady.use_gethrtime = False return time.time() - monotonic.use_clock_highres = (hasattr(time, 'clock_gettime') + steady.use_clock_highres = (hasattr(time, 'clock_gettime') and hasattr(time, 'CLOCK_HIGHRES')) - monotonic.use_gethrtime = True + steady.use_gethrtime = True elif hasattr(time, "clock_gettime"): - def monotonic(): - while monotonic.clocks: + def steady(): + while steady.clocks: try: - clk_id = monotonic.clocks[0] + clk_id = steady.clocks[0] return time.clock_gettime(clk_id) except OSError: - del monotonic.clocks[0] + del steady.clocks[0] return time.time() - monotonic.clocks = [] + steady.clocks = [] if hasattr(time, 'CLOCK_HIGHRES'): - monotonic.clocks.append(time.CLOCK_HIGHRES) - monotonic.clocks.append(time.CLOCK_MONOTONIC) + steady.clocks.append(time.CLOCK_HIGHRES) + steady.clocks.append(time.CLOCK_MONOTONIC) else: - def monotonic(): + def steady(): return time.time() On Windows, QueryPerformanceCounter() is not used even though it has a @@ -160,10 +158,10 @@ .. note:: - time.monotonic() detects GetTickCount() integer overflow (32 bits, + time.steady() detects GetTickCount() integer overflow (32 bits, roll-over after 49.7 days): it increases a delta by 2\ :sup:`32` each time than an overflow is detected. The delta is stored in the - process-local state and so the value of time.monotonic() may be + process-local state and so the value of time.steady() may be different in two Python processes. @@ -185,15 +183,15 @@ # hardware does not support a high-resolution performance # counter for example highres.use_performance_counter = False - if highres.use_monotonic: + if highres.use_steady: # Monotonic clock is preferred over system clock try: - return time.monotonic() + return time.steady() except OSError: - highres.use_monotonic = False + highres.use_steady = False return time.time() highres.use_performance_counter = (os.name == 'nt') - highres.use_monotonic = hasattr(time, 'monotonic') + highres.use_steady = hasattr(time, 'steady') time.get_clock_info(name) ------------------------- @@ -202,7 +200,7 @@ * "clock": time.clock() * "highres": time.highres() - * "monotonic": time.monotonic() + * "steady": time.steady() * "time": time.time() Return a dictionary with the following keys: @@ -766,10 +764,11 @@ * time.timer(): "it would be too easy to confuse with (or misspell as) time.time()" -time.monotonic(): +time.steady(): -* time.steady(): no OS provides a clock advancing at a steady rate, so - "steady" should be avoided. +* time.monotonic(): QueryPerformanceCounter() is monotonic but it is not used + by time.steady() because it is not steady, and it is surprising to have to + check for time.get_clock_info('monotonic')['is_monotonic']. * time.try_monotonic(): it is a clear and obvious solution for the use-case of "I prefer the monotonic clock, if it is available, otherwise I'll take my chances with a best-effect clock." -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 3 01:45:51 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 03 Apr 2012 01:45:51 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_time=2Esteady?= =?utf8?q?=28=29_pseudo-code?= Message-ID: http://hg.python.org/peps/rev/6048daf4d45c changeset: 4192:6048daf4d45c user: Victor Stinner date: Tue Apr 03 01:45:49 2012 +0200 summary: PEP 418: Fix time.steady() pseudo-code GetTickCount[64] returns a number of milliseconds, not a number of seconds. files: pep-0418.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -97,7 +97,7 @@ # GetTickCount64() requires Windows Vista, Server 2008 or later if hasattr(time, '_GetTickCount64'): def steady(): - return _time.GetTickCount64() + return _time.GetTickCount64() * 1e-3 else: def steady(): ticks = _time.GetTickCount() @@ -105,7 +105,7 @@ # Integer overflow detected steady.delta += 2**32 steady.last = ticks - return ticks + steady.delta + return (ticks + steady.delta) * 1e-3 steady.last = 0 steady.delta = 0 -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 3 02:34:27 2012 From: python-checkins at python.org (brett.cannon) Date: Tue, 03 Apr 2012 02:34:27 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_If_a_module_injects_somethi?= =?utf8?q?ng_into_sys=2Emodules_as_a_side-effect_of?= Message-ID: http://hg.python.org/cpython/rev/a40cd5976215 changeset: 76081:a40cd5976215 parent: 76072:bac033e488b4 user: Brett Cannon date: Mon Apr 02 20:33:56 2012 -0400 summary: If a module injects something into sys.modules as a side-effect of importation, then respect that injection. Discovered thanks to Lib/xml/parsers/expat.py injecting xml.parsers.expat.errors and etree now importing that directly as a module. files: Lib/importlib/_bootstrap.py | 3 ++ Lib/importlib/test/import_/test_packages.py | 13 ++++++++++ 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -927,6 +927,9 @@ if parent: if parent not in sys.modules: import_(parent) + # Crazy side-effects! + if name in sys.modules: + return sys.modules[name] # Backwards-compatibility; be nicer to skip the dict lookup. parent_module = sys.modules[parent] try: diff --git a/Lib/importlib/test/import_/test_packages.py b/Lib/importlib/test/import_/test_packages.py --- a/Lib/importlib/test/import_/test_packages.py +++ b/Lib/importlib/test/import_/test_packages.py @@ -27,6 +27,19 @@ with self.assertRaises(ImportError): import_util.import_('sys.no_submodules_here') + def test_module_not_package_but_side_effects(self): + # If a module injects something into sys.modules as a side-effect, then + # pick up on that fact. + name = 'mod' + subname = name + '.b' + def module_injection(): + sys.modules[subname] = 'total bunk' + mock_modules = util.mock_modules('mod', + module_code={'mod': module_injection}) + with mock_modules as mock: + with util.import_state(meta_path=[mock]): + submodule = import_util.import_(subname) + def test_main(): from test.support import run_unittest -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 02:34:28 2012 From: python-checkins at python.org (brett.cannon) Date: Tue, 03 Apr 2012 02:34:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/d0e4e3ef224e changeset: 76082:d0e4e3ef224e parent: 76081:a40cd5976215 parent: 76080:8ba72c0987dc user: Brett Cannon date: Mon Apr 02 20:34:20 2012 -0400 summary: merge files: Doc/library/time.rst | 16 +++++ Lib/test/test_decimal.py | 70 ------------------------- Lib/test/test_thread.py | 1 - Lib/test/test_time.py | 11 +++ Modules/_decimal/_decimal.c | 10 +- Modules/timemodule.c | 33 +++++++++++ 6 files changed, 65 insertions(+), 76 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -151,6 +151,13 @@ .. versionadded:: 3.3 +.. function:: clock_settime(clk_id, time) + + Set the time of the specified clock *clk_id*. + + .. versionadded:: 3.3 + + .. data:: CLOCK_REALTIME System-wide real-time clock. Setting this clock requires appropriate @@ -159,6 +166,15 @@ .. versionadded:: 3.3 +.. data:: CLOCK_HIGHRES + + The Solaris OS has a CLOCK_HIGHRES timer that attempts to use an optimal + hardware source, and may give close to nanosecond resolution. CLOCK_HIGHRES + is the nonadjustable, high-resolution clock. + + .. versionadded:: 3.3 + + .. data:: CLOCK_MONOTONIC Clock that cannot be set and represents monotonic time since some diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -56,76 +56,6 @@ fractions = {C:cfractions, P:pfractions} sys.modules['decimal'] = orig_sys_decimal -############ RunFirst ############ -class RunFirst(unittest.TestCase): - - def setUp(self): - self.save_default = self.decimal.DefaultContext.copy() - - def tearDown(self): - DefaultContext = self.decimal.DefaultContext - - DefaultContext.prec = self.save_default.prec - DefaultContext.rounding = self.save_default.rounding - DefaultContext.Emax = self.save_default.Emax - DefaultContext.Emin = self.save_default.Emin - DefaultContext.capitals = self.save_default.capitals - DefaultContext.clamp = self.save_default.clamp - DefaultContext.flags = self.save_default.flags - DefaultContext.traps = self.save_default.traps - - self.decimal.setcontext(self.decimal.DefaultContext) - - def test_00default_context(self): - # The test depends on the fact that getcontext() is called - # for the first time. - DefaultContext = self.decimal.DefaultContext - ROUND_05UP = self.decimal.ROUND_05UP - Clamped = self.decimal.Clamped - InvalidOperation = self.decimal.InvalidOperation - - DefaultContext.prec = 5001 - DefaultContext.rounding = ROUND_05UP - DefaultContext.Emax = 10025 - DefaultContext.Emin = -10025 - DefaultContext.capitals = 0 - DefaultContext.clamp = 1 - DefaultContext.flags[InvalidOperation] = True - DefaultContext.clear_traps() - DefaultContext.traps[Clamped] = True - - # implicit initialization on first access - c = self.decimal.getcontext() - - self.assertEqual(c.prec, 5001) - self.assertEqual(c.rounding, ROUND_05UP) - self.assertEqual(c.Emax, 10025) - self.assertEqual(c.Emin, -10025) - self.assertEqual(c.capitals, 0) - self.assertEqual(c.clamp, 1) - for k in c.flags: - self.assertFalse(c.flags[k]) - for k in c.traps: - if k is Clamped: - self.assertTrue(c.traps[k]) - else: - self.assertFalse(c.traps[k]) - - # explicit initialization - self.decimal.setcontext(DefaultContext) - c = self.decimal.getcontext() - for k in c.flags: - self.assertFalse(c.flags[k]) - -class CRunFirst(RunFirst): - decimal = C -class PyRunFirst(RunFirst): - decimal = P -if C: - run_unittest(CRunFirst, PyRunFirst) -else: - run_unittest(PyRunFirst) -############ END RunFirst ############ # Useful Test Constant Signals = { diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -132,7 +132,6 @@ # See issue #14474 def task(): started.release() - sys.stderr = stderr raise SyntaxError def mywrite(self, *args): try: diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -47,6 +47,17 @@ self.assertGreater(res, 0.0) self.assertLessEqual(res, 1.0) + @unittest.skipUnless(hasattr(time, 'clock_settime'), + 'need time.clock_settime()') + def test_clock_settime(self): + t = time.clock_gettime(time.CLOCK_REALTIME) + try: + time.clock_settime(time.CLOCK_REALTIME, t) + except PermissionError: + pass + + self.assertRaises(OSError, time.clock_settime, time.CLOCK_MONOTONIC, 0) + def test_conversions(self): self.assertEqual(time.ctime(self.t), time.asctime(time.localtime(self.t))) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1510,7 +1510,7 @@ #define CURRENT_CONTEXT_ADDR(ctx) \ ctx = CTX(current_context()) -/* Return current context, increment reference */ +/* Return a new reference to the current context */ static PyObject * PyDec_GetCurrentContext(void) { @@ -1614,7 +1614,7 @@ ctx = CTX(_c_t_x_o_b_j); \ } -/* Return current context, increment reference */ +/* Return a new reference to the current context */ static PyObject * PyDec_GetCurrentContext(void) { @@ -1759,7 +1759,7 @@ 0, /* tp_print */ (getattrfunc) 0, /* tp_getattr */ (setattrfunc) 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc) 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -2699,7 +2699,7 @@ /******************************************************************************/ -/* Implicit conversions to Decimal */ +/* Implicit conversions to Decimal */ /******************************************************************************/ /* Try to convert PyObject v to a new PyDecObject conv. If the conversion @@ -2796,7 +2796,7 @@ /******************************************************************************/ -/* Implicit conversions to Decimal for comparison */ +/* Implicit conversions to Decimal for comparison */ /******************************************************************************/ /* Convert rationals for comparison */ diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -158,6 +158,33 @@ "clock_gettime(clk_id) -> floating point number\n\ \n\ Return the time of the specified clock clk_id."); + +static PyObject * +time_clock_settime(PyObject *self, PyObject *args) +{ + clockid_t clk_id; + PyObject *obj; + struct timespec tp; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) + return NULL; + + if (_PyTime_ObjectToTimespec(obj, &tp.tv_sec, &tp.tv_nsec) == -1) + return NULL; + + ret = clock_settime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(clock_settime_doc, +"clock_settime(clk_id, time)\n\ +\n\ +Set the time of the specified clock clk_id."); #endif #ifdef HAVE_CLOCK_GETRES @@ -962,6 +989,9 @@ #ifdef CLOCK_MONOTONIC_RAW PyModule_AddIntMacro(m, CLOCK_MONOTONIC_RAW); #endif +#ifdef CLOCK_HIGHRES + PyModule_AddIntMacro(m, CLOCK_HIGHRES); +#endif #ifdef CLOCK_PROCESS_CPUTIME_ID PyModule_AddIntMacro(m, CLOCK_PROCESS_CPUTIME_ID); #endif @@ -980,6 +1010,9 @@ #ifdef HAVE_CLOCK_GETTIME {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, #endif +#ifdef HAVE_CLOCK_GETTIME + {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, +#endif #ifdef HAVE_CLOCK_GETRES {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, #endif -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Apr 3 05:34:22 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 03 Apr 2012 05:34:22 +0200 Subject: [Python-checkins] Daily reference leaks (d0e4e3ef224e): sum=3 Message-ID: results for d0e4e3ef224e on branch "default" -------------------------------------------- test_thread leaked [1, 1, 1] references, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog9pcCae', '-x'] From python-checkins at python.org Tue Apr 3 06:35:50 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 03 Apr 2012 06:35:50 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_fix_parse=5Fsyn?= =?utf8?q?tax=5Ferror_to_clean_up_its_resources?= Message-ID: http://hg.python.org/cpython/rev/013766e7a6eb changeset: 76083:013766e7a6eb branch: 2.7 parent: 76074:2b7aff01ca89 user: Benjamin Peterson date: Tue Apr 03 00:30:38 2012 -0400 summary: fix parse_syntax_error to clean up its resources files: Python/pythonrun.c | 56 ++++++++++++++++++++------------- 1 files changed, 34 insertions(+), 22 deletions(-) diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -989,55 +989,67 @@ return PyArg_ParseTuple(err, "O(ziiz)", message, filename, lineno, offset, text); + *message = NULL; + /* new style errors. `err' is an instance */ - - if (! (v = PyObject_GetAttrString(err, "msg"))) - goto finally; - *message = v; - - if (!(v = PyObject_GetAttrString(err, "filename"))) - goto finally; - if (v == Py_None) - *filename = NULL; - else if (! (*filename = PyString_AsString(v))) + *message = PyObject_GetAttrString(err, "msg"); + if (!*message) goto finally; - Py_DECREF(v); - if (!(v = PyObject_GetAttrString(err, "lineno"))) + v = PyObject_GetAttrString(err, "filename"); + if (!v) + goto finally; + if (v == Py_None) { + Py_DECREF(v); + *filename = NULL; + } + else { + *filename = PyString_AsString(v); + Py_DECREF(v); + if (!*filename) + goto finally; + } + + v = PyObject_GetAttrString(err, "lineno"); + if (!v) goto finally; hold = PyInt_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *lineno = (int)hold; - if (!(v = PyObject_GetAttrString(err, "offset"))) + v = PyObject_GetAttrString(err, "offset"); + if (!v) goto finally; if (v == Py_None) { *offset = -1; Py_DECREF(v); - v = NULL; } else { hold = PyInt_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *offset = (int)hold; } - if (!(v = PyObject_GetAttrString(err, "text"))) + v = PyObject_GetAttrString(err, "text"); + if (!v) goto finally; - if (v == Py_None) + if (v == Py_None) { + Py_DECREF(v); *text = NULL; - else if (! (*text = PyString_AsString(v))) - goto finally; - Py_DECREF(v); + } + else { + *text = PyString_AsString(v); + Py_DECREF(v); + if (!*text) + goto finally; + } return 1; finally: - Py_XDECREF(v); + Py_XDECREF(*message); return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 06:35:52 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 03 Apr 2012 06:35:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_fix_parse=5Fsyn?= =?utf8?q?tax=5Ferror_to_clean_up_its_resources?= Message-ID: http://hg.python.org/cpython/rev/43606a4085b0 changeset: 76084:43606a4085b0 branch: 3.2 parent: 76075:98ab6e322c40 user: Benjamin Peterson date: Tue Apr 03 00:30:38 2012 -0400 summary: fix parse_syntax_error to clean up its resources files: Python/pythonrun.c | 57 ++++++++++++++++++++------------- 1 files changed, 34 insertions(+), 23 deletions(-) diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1335,56 +1335,67 @@ return PyArg_ParseTuple(err, "O(ziiz)", message, filename, lineno, offset, text); + *message = NULL; + /* new style errors. `err' is an instance */ - - if (! (v = PyObject_GetAttrString(err, "msg"))) - goto finally; - *message = v; - - if (!(v = PyObject_GetAttrString(err, "filename"))) - goto finally; - if (v == Py_None) - *filename = NULL; - else if (! (*filename = _PyUnicode_AsString(v))) + *message = PyObject_GetAttrString(err, "msg"); + if (!*message) goto finally; - Py_DECREF(v); - if (!(v = PyObject_GetAttrString(err, "lineno"))) + v = PyObject_GetAttrString(err, "filename"); + if (!v) + goto finally; + if (v == Py_None) { + Py_DECREF(v); + *filename = NULL; + } + else { + *filename = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*filename) + goto finally; + } + + v = PyObject_GetAttrString(err, "lineno"); + if (!v) goto finally; hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *lineno = (int)hold; - if (!(v = PyObject_GetAttrString(err, "offset"))) + v = PyObject_GetAttrString(err, "offset"); + if (!v) goto finally; if (v == Py_None) { *offset = -1; Py_DECREF(v); - v = NULL; } else { hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *offset = (int)hold; } - if (!(v = PyObject_GetAttrString(err, "text"))) + v = PyObject_GetAttrString(err, "text"); + if (!v) goto finally; - if (v == Py_None) + if (v == Py_None) { + Py_DECREF(v); *text = NULL; - else if (!PyUnicode_Check(v) || - !(*text = _PyUnicode_AsString(v))) - goto finally; - Py_DECREF(v); + } + else { + *text = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*text) + goto finally; + } return 1; finally: - Py_XDECREF(v); + Py_XDECREF(*message); return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 06:35:53 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 03 Apr 2012 06:35:53 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/ff7587546a1d changeset: 76085:ff7587546a1d parent: 76076:e97940f701be parent: 76084:43606a4085b0 user: Benjamin Peterson date: Tue Apr 03 00:35:36 2012 -0400 summary: merge 3.2 files: Python/pythonrun.c | 57 ++++++++++++++++++++------------- 1 files changed, 34 insertions(+), 23 deletions(-) diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1356,56 +1356,67 @@ _Py_IDENTIFIER(offset); _Py_IDENTIFIER(text); + *message = NULL; + /* new style errors. `err' is an instance */ - - if (! (v = _PyObject_GetAttrId(err, &PyId_msg))) - goto finally; - *message = v; - - if (!(v = _PyObject_GetAttrId(err, &PyId_filename))) - goto finally; - if (v == Py_None) - *filename = NULL; - else if (! (*filename = _PyUnicode_AsString(v))) + *message = _PyObject_GetAttrId(err, &PyId_msg); + if (!*message) goto finally; - Py_DECREF(v); - if (!(v = _PyObject_GetAttrId(err, &PyId_lineno))) + v = _PyObject_GetAttrId(err, &PyId_filename); + if (!v) + goto finally; + if (v == Py_None) { + Py_DECREF(v); + *filename = NULL; + } + else { + *filename = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*filename) + goto finally; + } + + v = _PyObject_GetAttrId(err, &PyId_lineno); + if (!v) goto finally; hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *lineno = (int)hold; - if (!(v = _PyObject_GetAttrId(err, &PyId_offset))) + v = _PyObject_GetAttrId(err, &PyId_offset); + if (!v) goto finally; if (v == Py_None) { *offset = -1; Py_DECREF(v); - v = NULL; } else { hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *offset = (int)hold; } - if (!(v = _PyObject_GetAttrId(err, &PyId_text))) + v = _PyObject_GetAttrId(err, &PyId_text); + if (!v) goto finally; - if (v == Py_None) + if (v == Py_None) { + Py_DECREF(v); *text = NULL; - else if (!PyUnicode_Check(v) || - !(*text = _PyUnicode_AsString(v))) - goto finally; - Py_DECREF(v); + } + else { + *text = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*text) + goto finally; + } return 1; finally: - Py_XDECREF(v); + Py_XDECREF(*message); return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 06:35:55 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 03 Apr 2012 06:35:55 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/05cfde25ded1 changeset: 76086:05cfde25ded1 parent: 76085:ff7587546a1d parent: 76082:d0e4e3ef224e user: Benjamin Peterson date: Tue Apr 03 00:35:44 2012 -0400 summary: merge heads files: Doc/library/time.rst | 16 ++++ Lib/importlib/_bootstrap.py | 3 + Lib/importlib/test/import_/test_packages.py | 13 +++ Lib/test/test_time.py | 11 +++ Modules/_decimal/_decimal.c | 10 +- Modules/timemodule.c | 33 ++++++++++ 6 files changed, 81 insertions(+), 5 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -151,6 +151,13 @@ .. versionadded:: 3.3 +.. function:: clock_settime(clk_id, time) + + Set the time of the specified clock *clk_id*. + + .. versionadded:: 3.3 + + .. data:: CLOCK_REALTIME System-wide real-time clock. Setting this clock requires appropriate @@ -159,6 +166,15 @@ .. versionadded:: 3.3 +.. data:: CLOCK_HIGHRES + + The Solaris OS has a CLOCK_HIGHRES timer that attempts to use an optimal + hardware source, and may give close to nanosecond resolution. CLOCK_HIGHRES + is the nonadjustable, high-resolution clock. + + .. versionadded:: 3.3 + + .. data:: CLOCK_MONOTONIC Clock that cannot be set and represents monotonic time since some diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -927,6 +927,9 @@ if parent: if parent not in sys.modules: import_(parent) + # Crazy side-effects! + if name in sys.modules: + return sys.modules[name] # Backwards-compatibility; be nicer to skip the dict lookup. parent_module = sys.modules[parent] try: diff --git a/Lib/importlib/test/import_/test_packages.py b/Lib/importlib/test/import_/test_packages.py --- a/Lib/importlib/test/import_/test_packages.py +++ b/Lib/importlib/test/import_/test_packages.py @@ -27,6 +27,19 @@ with self.assertRaises(ImportError): import_util.import_('sys.no_submodules_here') + def test_module_not_package_but_side_effects(self): + # If a module injects something into sys.modules as a side-effect, then + # pick up on that fact. + name = 'mod' + subname = name + '.b' + def module_injection(): + sys.modules[subname] = 'total bunk' + mock_modules = util.mock_modules('mod', + module_code={'mod': module_injection}) + with mock_modules as mock: + with util.import_state(meta_path=[mock]): + submodule = import_util.import_(subname) + def test_main(): from test.support import run_unittest diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -47,6 +47,17 @@ self.assertGreater(res, 0.0) self.assertLessEqual(res, 1.0) + @unittest.skipUnless(hasattr(time, 'clock_settime'), + 'need time.clock_settime()') + def test_clock_settime(self): + t = time.clock_gettime(time.CLOCK_REALTIME) + try: + time.clock_settime(time.CLOCK_REALTIME, t) + except PermissionError: + pass + + self.assertRaises(OSError, time.clock_settime, time.CLOCK_MONOTONIC, 0) + def test_conversions(self): self.assertEqual(time.ctime(self.t), time.asctime(time.localtime(self.t))) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1510,7 +1510,7 @@ #define CURRENT_CONTEXT_ADDR(ctx) \ ctx = CTX(current_context()) -/* Return current context, increment reference */ +/* Return a new reference to the current context */ static PyObject * PyDec_GetCurrentContext(void) { @@ -1614,7 +1614,7 @@ ctx = CTX(_c_t_x_o_b_j); \ } -/* Return current context, increment reference */ +/* Return a new reference to the current context */ static PyObject * PyDec_GetCurrentContext(void) { @@ -1759,7 +1759,7 @@ 0, /* tp_print */ (getattrfunc) 0, /* tp_getattr */ (setattrfunc) 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc) 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -2699,7 +2699,7 @@ /******************************************************************************/ -/* Implicit conversions to Decimal */ +/* Implicit conversions to Decimal */ /******************************************************************************/ /* Try to convert PyObject v to a new PyDecObject conv. If the conversion @@ -2796,7 +2796,7 @@ /******************************************************************************/ -/* Implicit conversions to Decimal for comparison */ +/* Implicit conversions to Decimal for comparison */ /******************************************************************************/ /* Convert rationals for comparison */ diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -158,6 +158,33 @@ "clock_gettime(clk_id) -> floating point number\n\ \n\ Return the time of the specified clock clk_id."); + +static PyObject * +time_clock_settime(PyObject *self, PyObject *args) +{ + clockid_t clk_id; + PyObject *obj; + struct timespec tp; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) + return NULL; + + if (_PyTime_ObjectToTimespec(obj, &tp.tv_sec, &tp.tv_nsec) == -1) + return NULL; + + ret = clock_settime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(clock_settime_doc, +"clock_settime(clk_id, time)\n\ +\n\ +Set the time of the specified clock clk_id."); #endif #ifdef HAVE_CLOCK_GETRES @@ -962,6 +989,9 @@ #ifdef CLOCK_MONOTONIC_RAW PyModule_AddIntMacro(m, CLOCK_MONOTONIC_RAW); #endif +#ifdef CLOCK_HIGHRES + PyModule_AddIntMacro(m, CLOCK_HIGHRES); +#endif #ifdef CLOCK_PROCESS_CPUTIME_ID PyModule_AddIntMacro(m, CLOCK_PROCESS_CPUTIME_ID); #endif @@ -980,6 +1010,9 @@ #ifdef HAVE_CLOCK_GETTIME {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, #endif +#ifdef HAVE_CLOCK_GETTIME + {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, +#endif #ifdef HAVE_CLOCK_GETRES {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 06:52:22 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 03 Apr 2012 06:52:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_add_XXX?= Message-ID: http://hg.python.org/cpython/rev/737f710a72c9 changeset: 76087:737f710a72c9 user: Benjamin Peterson date: Tue Apr 03 00:52:18 2012 -0400 summary: add XXX files: Doc/whatsnew/3.3.rst | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -486,6 +486,8 @@ (:issue:`10516`) +.. XXX mention new error messages for passing wrong number of arguments to functions + New and Improved Modules ======================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 08:48:12 2012 From: python-checkins at python.org (andrew.svetlov) Date: Tue, 03 Apr 2012 08:48:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_reformat_code_to_follow_PEP?= =?utf8?q?8?= Message-ID: http://hg.python.org/cpython/rev/db0063ce8a5c changeset: 76088:db0063ce8a5c user: Andrew Svetlov date: Tue Apr 03 09:39:47 2012 +0300 summary: reformat code to follow PEP8 files: Lib/tkinter/font.py | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Lib/tkinter/font.py b/Lib/tkinter/font.py --- a/Lib/tkinter/font.py +++ b/Lib/tkinter/font.py @@ -10,19 +10,21 @@ import tkinter + # weight/slant NORMAL = "normal" ROMAN = "roman" BOLD = "bold" ITALIC = "italic" + def nametofont(name): """Given the name of a tk named font, returns a Font representation. """ return Font(name=name, exists=True) + class Font: - """Represents a named font. Constructor options are: @@ -63,7 +65,8 @@ options[args[i][1:]] = args[i+1] return options - def __init__(self, root=None, font=None, name=None, exists=False, **options): + def __init__(self, root=None, font=None, name=None, exists=False, + **options): if not root: root = tkinter._default_root if font: @@ -138,8 +141,7 @@ *self._set(options)) else: return self._mkdict( - self._split(self._call("font", "config", self.name)) - ) + self._split(self._call("font", "config", self.name))) configure = config @@ -155,8 +157,7 @@ if options: return int( - self._call("font", "metrics", self.name, self._get(options)) - ) + self._call("font", "metrics", self.name, self._get(options))) else: res = self._split(self._call("font", "metrics", self.name)) options = {} @@ -164,18 +165,21 @@ options[res[i][1:]] = int(res[i+1]) return options + def families(root=None): "Get font families (as a tuple)" if not root: root = tkinter._default_root return root.tk.splitlist(root.tk.call("font", "families")) + def names(root=None): "Get names of defined fonts (as a tuple)" if not root: root = tkinter._default_root return root.tk.splitlist(root.tk.call("font", "names")) + # -------------------------------------------------------------------- # test stuff -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 08:48:14 2012 From: python-checkins at python.org (andrew.svetlov) Date: Tue, 03 Apr 2012 08:48:14 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=23802310=3A_Generate?= =?utf8?q?_always_unique_tkinter_font_names_if_not_directly_passed?= Message-ID: http://hg.python.org/cpython/rev/a77e23135675 changeset: 76089:a77e23135675 user: Andrew Svetlov date: Tue Apr 03 09:48:07 2012 +0300 summary: Issue #802310: Generate always unique tkinter font names if not directly passed files: Lib/tkinter/font.py | 5 ++++- Misc/NEWS | 2 ++ 2 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Lib/tkinter/font.py b/Lib/tkinter/font.py --- a/Lib/tkinter/font.py +++ b/Lib/tkinter/font.py @@ -8,6 +8,7 @@ __version__ = "0.9" +import itertools import tkinter @@ -46,6 +47,8 @@ """ + counter = itertools.count(1) + def _set(self, kw): options = [] for k, v in kw.items(): @@ -75,7 +78,7 @@ else: font = self._set(options) if not name: - name = "font" + str(id(self)) + name = "font" + str(next(self.counter)) self.name = name if exists: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,8 @@ Library ------- +- Issue #802310: Generate always unique tkinter font names if not directly passed. + - Issue #14151: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 08:57:31 2012 From: python-checkins at python.org (georg.brandl) Date: Tue, 03 Apr 2012 08:57:31 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_Closes_=2314479=3A_replace?= =?utf8?q?_transplant_advice_with_graft?= Message-ID: http://hg.python.org/devguide/rev/b1dfbaae4458 changeset: 500:b1dfbaae4458 user: Georg Brandl date: Tue Apr 03 08:57:38 2012 +0200 summary: Closes #14479: replace transplant advice with graft files: committing.rst | 35 +++++++++++++++-------------------- faq.rst | 2 +- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/committing.rst b/committing.rst --- a/committing.rst +++ b/committing.rst @@ -308,30 +308,27 @@ '''''''''''''''''''''''''''''' Let's say you have committed your changes as changeset ``a7df1a869e4a`` -in the 3.2 branch and now want to port it to 2.7. This is simple. First -update your working copy to the 2.7 branch, then import the patch:: +in the 3.2 branch and now want to port it to 2.7. This is simple using +the "graft" command, which uses Mercurial's merge functionality to +cherry-pick:: + + hg update 2.7 + hg graft a7df1a869e4a + # Compile; run the test suite + +Graft always commits automatically, except in case of conflicts, when you +have to resolve them and run ``hg graft --continue`` afterwards. + +Another method is using "export" and "import": this has the advantage that +you can run the test suite before committing, but the disadvantage that +in case of conflicts, you will only get ``.rej`` files, not inline merge +markers. :: hg update 2.7 hg export a7df1a869e4a | hg import --no-commit - # Compile; run the test suite hg commit -You can also use the `transplant extension`_:: - - hg update 2.7 - hg transplant a7df1a869e4a - # Compile; run the test suite - -If you often get failures porting patches this way, you should consider -using the :ref:`mpatch ` utility. - - -.. warning:: - transplant always commits automatically. This breaks the - "run the test suite before committing" rule. We could advocate using - "hg qimport -r tip -P" afterwards but that would add another level of - complexity. - Using several working copies '''''''''''''''''''''''''''' @@ -408,8 +405,6 @@ someone else that haven't been merged yet. -.. _transplant extension: http://mercurial.selenic.com/wiki/TransplantExtension - .. seealso:: `Merging work `_, diff --git a/faq.rst b/faq.rst --- a/faq.rst +++ b/faq.rst @@ -758,7 +758,7 @@ Mercurial comes with many bundled extensions which can be explicitly enabled. You can get a list of them by typing ``hg help extensions``. Some of these extensions, such as ``color``, can prettify output; others, such as ``fetch`` -or ``transplant``, add new Mercurial commands. +or ``graphlog``, add new Mercurial commands. There are also many `configuration options`_ to tweak various aspects of the command line and other Mercurial behaviour; typing `man hgrc`_ displays -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Tue Apr 3 09:12:45 2012 From: python-checkins at python.org (georg.brandl) Date: Tue, 03 Apr 2012 09:12:45 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_devguide=3A_fix_some_typos?= Message-ID: http://hg.python.org/devguide/rev/9cf7dc7aca86 changeset: 501:9cf7dc7aca86 user: Georg Brandl date: Tue Apr 03 09:12:53 2012 +0200 summary: devguide: fix some typos files: buildbots.rst | 2 +- committing.rst | 4 ++-- communication.rst | 4 ++-- compiler.rst | 2 +- documenting.rst | 6 +++--- faq.rst | 6 +++--- gdb.rst | 2 +- grammar.rst | 4 ++-- triaging.rst | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/buildbots.rst b/buildbots.rst --- a/buildbots.rst +++ b/buildbots.rst @@ -156,7 +156,7 @@ ------------------ While we try to make the test suite as reliable as possible, some tests do -not reach a perfect level of reproduceability. Some of them will sometimes +not reach a perfect level of reproducibility. Some of them will sometimes display spurious failures, depending on various conditions. Here are common offenders: diff --git a/committing.rst b/committing.rst --- a/committing.rst +++ b/committing.rst @@ -399,7 +399,7 @@ If you are coming from Subversion, you might be surprised by Mercurial :ref:`merges `. Despite its name, ``svnmerge`` is different from ``hg merge``: while ``svnmerge`` -allows to cherrypick individual revisions, ``hg merge`` can only merge whole +allows to cherry-pick individual revisions, ``hg merge`` can only merge whole lines of development in the repository's :abbr:`DAG (directed acyclic graph)`. Therefore, ``hg merge`` might force you to review outstanding changesets by someone else that haven't been merged yet. @@ -503,7 +503,7 @@ In this scheme, your work will probably consist of many commits (some of them merges). If you want to upload a patch for review somewhere, you need -a single agregate patch. This is where having a dedicated named branch +a single aggregate patch. This is where having a dedicated named branch ``mywork`` gets handy. First ensure that you have pulled *and merged* all changes from the main diff --git a/communication.rst b/communication.rst --- a/communication.rst +++ b/communication.rst @@ -48,8 +48,8 @@ A complete list of Python mailing lists can be found at http://mail.python.org. Most lists are also mirrored at http://news.gmane.org/ and can be read and -posted to in various ways, including via web browers, NNTP newsreaders, and -RSS feed readers. +posted to in various ways, including via web browsers, NNTP newsreaders, and +RSS feed readers. .. _issue tracker: http://bugs.python.org .. _new-bugs-announce: http://mail.python.org/mailman/listinfo/new-bugs-announce diff --git a/compiler.rst b/compiler.rst --- a/compiler.rst +++ b/compiler.rst @@ -186,7 +186,7 @@ of Python uses reference counting, there is extra support added to the arena to cleanup each PyObject that was allocated. These cases are very rare. However, if you've allocated a PyObject, you must tell -the arena about it by calling PyArena_AddPyObject(). +the arena about it by calling ``PyArena_AddPyObject()``. Parse Tree to AST diff --git a/documenting.rst b/documenting.rst --- a/documenting.rst +++ b/documenting.rst @@ -6,7 +6,7 @@ The Python language has a substantial body of documentation, much of it contributed by various authors. The markup used for the Python documentation is `reStructuredText`_, developed by the `docutils`_ project, amended by custom -directives and using a toolset named `Sphinx`_ to postprocess the HTML output. +directives and using a toolset named `Sphinx`_ to post-process the HTML output. This document describes the style guide for our documentation as well as the custom reStructuredText markup introduced by Sphinx to support Python @@ -108,7 +108,7 @@ Apple style guide recommends the use of title case in section titles. However, rules for which words should be capitalized in title case -vary greaty between publications. +vary greatly between publications. In Python documentation, use of sentence case in section titles is preferable, but consistency within a unit is more important than @@ -327,7 +327,7 @@ List markup is natural: just place an asterisk at the start of a paragraph and indent properly. The same goes for numbered lists; they can also be -autonumbered using a ``#`` sign:: +automatically numbered using a ``#`` sign:: * This is a bulleted list. * It has two items, the second diff --git a/faq.rst b/faq.rst --- a/faq.rst +++ b/faq.rst @@ -475,7 +475,7 @@ hg add PATH If ``PATH`` is a directory, Mercurial will recursively add any files in that -directory and its descendents. +directory and its descendants. If you want Mercurial to figure out by itself which files should be added and/or removed, just run:: @@ -534,7 +534,7 @@ .. note:: If you do not like the default text editor Mercurial uses for - entering commmit messages, you may specify a different editor, + entering commit messages, you may specify a different editor, either by changing the ``EDITOR`` environment variable or by setting a Mercurial-specific editor in your global ``.hgrc`` with the ``editor`` option in the ``[ui]`` section. @@ -562,7 +562,7 @@ hg status will list any pending changes in the working copy. These changes will get -commited to the local repository if you issue an ``hg commit`` without +committed to the local repository if you issue an ``hg commit`` without specifying any path. Some diff --git a/gdb.rst b/gdb.rst --- a/gdb.rst +++ b/gdb.rst @@ -131,7 +131,7 @@ the python source. ``py-up`` and ``py-down`` - The ``py-up`` and ``py-down`` commands are analagous to gdb's regular ``up`` + The ``py-up`` and ``py-down`` commands are analogous to gdb's regular ``up`` and ``down`` commands, but try to move at the level of CPython frames, rather than C frames. diff --git a/grammar.rst b/grammar.rst --- a/grammar.rst +++ b/grammar.rst @@ -39,7 +39,7 @@ * Parser/pgen needs to be rerun to regenerate Include/graminit.h and Python/graminit.c. (make should handle this for you.) -* Python/symbtable.c: This handles the symbol collection pass +* Python/symtable.c: This handles the symbol collection pass that happens immediately before the compilation pass. * Python/compile.c: You will need to create or modify the @@ -60,7 +60,7 @@ * Documentation must be written! -* After everything's been checked in, you're likely to see a new +* After everything has been checked in, you're likely to see a new change to Python/Python-ast.c. This is because this (generated) file contains the hg version of the source from which it was generated. There's no way to avoid this; you just diff --git a/triaging.rst b/triaging.rst --- a/triaging.rst +++ b/triaging.rst @@ -180,7 +180,7 @@ attention. Use the :ref:`experts` to know who wants to be added to the nosy list for issues targeting specific areas. -If you have Javascript enabled and permission to edit the nosy list, you can +If you have JavaScript enabled and permission to edit the nosy list, you can use the ``[+]`` button to add yourself to the nosy (remember to click on "Submit Changes" afterwards). Note that you are added to the nosy automatically when you submit a message. -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Tue Apr 3 09:16:40 2012 From: python-checkins at python.org (georg.brandl) Date: Tue, 03 Apr 2012 09:16:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Move_ChainMap_versionadded_?= =?utf8?q?to_be_less_ambiguous=2E?= Message-ID: http://hg.python.org/cpython/rev/555f5fe53341 changeset: 76090:555f5fe53341 user: Georg Brandl date: Tue Apr 03 09:16:46 2012 +0200 summary: Move ChainMap versionadded to be less ambiguous. files: Doc/library/collections.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -41,6 +41,8 @@ :class:`ChainMap` objects ------------------------- +.. versionadded:: 3.3 + A :class:`ChainMap` class is provided for quickly linking a number of mappings so they can be treated as a single unit. It is often much faster than creating a new dictionary and running multiple :meth:`~dict.update` calls. @@ -91,8 +93,6 @@ The use-cases also parallel those for the builtin :func:`super` function. A reference to ``d.parents`` is equivalent to: ``ChainMap(*d.maps[1:])``. - .. versionadded:: 3.3 - Example of simulating Python's internal lookup chain:: import builtins -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 13:12:04 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 03 Apr 2012 13:12:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314288=3A_Serializa?= =?utf8?q?tion_support_for_builtin_iterators=2E?= Message-ID: http://hg.python.org/cpython/rev/4ff234337e24 changeset: 76091:4ff234337e24 user: Kristj?n Valur J?nsson date: Tue Apr 03 10:49:41 2012 +0000 summary: Issue #14288: Serialization support for builtin iterators. files: Include/iterobject.h | 2 + Lib/test/seq_tests.py | 7 + Lib/test/test_array.py | 14 + Lib/test/test_builtin.py | 41 + Lib/test/test_bytes.py | 18 + Lib/test/test_deque.py | 13 + Lib/test/test_dict.py | 54 + Lib/test/test_enumerate.py | 30 +- Lib/test/test_iter.py | 43 +- Lib/test/test_itertools.py | 386 +++++++++- Lib/test/test_list.py | 28 + Lib/test/test_range.py | 24 +- Lib/test/test_set.py | 21 + Lib/test/test_tuple.py | 29 + Modules/_collectionsmodule.c | 93 ++- Modules/arraymodule.c | 30 +- Modules/itertoolsmodule.c | 890 +++++++++++++++++++++- Objects/bytearrayobject.c | 36 +- Objects/bytesobject.c | 34 + Objects/dictobject.c | 53 + Objects/enumobject.c | 50 +- Objects/iterobject.c | 60 +- Objects/listobject.c | 80 ++ Objects/rangeobject.c | 92 ++ Objects/setobject.c | 45 +- Objects/tupleobject.c | 31 + Objects/unicodeobject.c | 34 + Python/bltinmodule.c | 56 +- 28 files changed, 2190 insertions(+), 104 deletions(-) diff --git a/Include/iterobject.h b/Include/iterobject.h --- a/Include/iterobject.h +++ b/Include/iterobject.h @@ -18,6 +18,8 @@ PyAPI_FUNC(PyObject *) PyCallIter_New(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyIter_GetBuiltin(const char *iter); + #ifdef __cplusplus } #endif diff --git a/Lib/test/seq_tests.py b/Lib/test/seq_tests.py --- a/Lib/test/seq_tests.py +++ b/Lib/test/seq_tests.py @@ -4,6 +4,7 @@ import unittest import sys +import pickle # Various iterables # This is used for checking the constructor (here and in test_deque.py) @@ -388,3 +389,9 @@ self.assertEqual(a.index(0, -4*sys.maxsize, 4*sys.maxsize), 2) self.assertRaises(ValueError, a.index, 0, 4*sys.maxsize,-4*sys.maxsize) self.assertRaises(ValueError, a.index, 2, 0, -10) + + def test_pickle(self): + lst = self.type2test([4, 5, 6, 7]) + lst2 = pickle.loads(pickle.dumps(lst)) + self.assertEqual(lst2, lst) + self.assertNotEqual(id(lst2), id(lst)) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -285,6 +285,20 @@ self.assertEqual(a.x, b.x) self.assertEqual(type(a), type(b)) + def test_iterator_pickle(self): + data = array.array(self.typecode, self.example) + orgit = iter(data) + d = pickle.dumps(orgit) + it = pickle.loads(d) + self.assertEqual(type(orgit), type(it)) + self.assertEqual(list(it), list(data)) + + if len(data): + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(list(it), list(data)[1:]) + def test_insert(self): a = array.array(self.typecode, self.example) a.insert(0, self.example[0]) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -14,6 +14,7 @@ import traceback from test.support import TESTFN, unlink, run_unittest, check_warnings from operator import neg +import pickle try: import pty, signal except ImportError: @@ -110,7 +111,30 @@ def __iter__(self): raise RuntimeError +def filter_char(arg): + return ord(arg) > ord("d") + +def map_char(arg): + return chr(ord(arg)+1) + class BuiltinTest(unittest.TestCase): + # Helper to check picklability + def check_iter_pickle(self, it, seq): + itorg = it + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), seq) + + #test the iterator after dropping one from it + it = pickle.loads(d) + try: + next(it) + except StopIteration: + return + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), seq[1:]) def test_import(self): __import__('sys') @@ -566,6 +590,11 @@ self.assertEqual(list(filter(lambda x: x>=3, (1, 2, 3, 4))), [3, 4]) self.assertRaises(TypeError, list, filter(42, (1, 2))) + def test_filter_pickle(self): + f1 = filter(filter_char, "abcdeabcde") + f2 = filter(filter_char, "abcdeabcde") + self.check_iter_pickle(f1, list(f2)) + def test_getattr(self): self.assertTrue(getattr(sys, 'stdout') is sys.stdout) self.assertRaises(TypeError, getattr, sys, 1) @@ -759,6 +788,11 @@ raise RuntimeError self.assertRaises(RuntimeError, list, map(badfunc, range(5))) + def test_map_pickle(self): + m1 = map(map_char, "Is this the real life?") + m2 = map(map_char, "Is this the real life?") + self.check_iter_pickle(m1, list(m2)) + def test_max(self): self.assertEqual(max('123123'), '3') self.assertEqual(max(1, 2, 3), 3) @@ -1300,6 +1334,13 @@ return i self.assertRaises(ValueError, list, zip(BadSeq(), BadSeq())) + def test_zip_pickle(self): + a = (1, 2, 3) + b = (4, 5, 6) + t = [(1, 4), (2, 5), (3, 6)] + z1 = zip(a, b) + self.check_iter_pickle(z1, t) + def test_format(self): # Test the basic machinery of the format() builtin. Don't test # the specifics of the various formatters diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -518,6 +518,24 @@ q = pickle.loads(ps) self.assertEqual(b, q) + def test_iterator_pickling(self): + for b in b"", b"a", b"abc", b"\xffab\x80", b"\0\0\377\0\0": + it = itorg = iter(self.type2test(b)) + data = list(self.type2test(b)) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), data) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + continue + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), data[1:]) + def test_strip(self): b = self.type2test(b'mississippi') self.assertEqual(b.strip(b'i'), b'mississipp') 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 @@ -471,6 +471,19 @@ ## self.assertNotEqual(id(d), id(e)) ## self.assertEqual(id(e), id(e[-1])) + def test_iterator_pickle(self): + data = deque(range(200)) + it = itorg = iter(data) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), list(data)) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(list(it), list(data)[1:]) + def test_deepcopy(self): mut = [10] d = deque([mut]) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -2,7 +2,9 @@ from test import support import collections, random, string +import collections.abc import gc, weakref +import pickle class DictTest(unittest.TestCase): @@ -803,6 +805,58 @@ pass self._tracked(MyDict()) + def test_iterator_pickling(self): + data = {1:"a", 2:"b", 3:"c"} + it = iter(data) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(sorted(it), sorted(data)) + + it = pickle.loads(d) + try: + drop = next(it) + except StopIteration: + return + d = pickle.dumps(it) + it = pickle.loads(d) + del data[drop] + self.assertEqual(sorted(it), sorted(data)) + + def test_itemiterator_pickling(self): + data = {1:"a", 2:"b", 3:"c"} + # dictviews aren't picklable, only their iterators + itorg = iter(data.items()) + d = pickle.dumps(itorg) + it = pickle.loads(d) + # note that the type of type of the unpickled iterator + # is not necessarily the same as the original. It is + # merely an object supporting the iterator protocol, yielding + # the same objects as the original one. + # self.assertEqual(type(itorg), type(it)) + self.assertTrue(isinstance(it, collections.abc.Iterator)) + self.assertEqual(dict(it), data) + + it = pickle.loads(d) + drop = next(it) + d = pickle.dumps(it) + it = pickle.loads(d) + del data[drop[0]] + self.assertEqual(dict(it), data) + + def test_valuesiterator_pickling(self): + data = {1:"a", 2:"b", 3:"c"} + # data.values() isn't picklable, only its iterator + it = iter(data.values()) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(sorted(list(it)), sorted(list(data.values()))) + + it = pickle.loads(d) + drop = next(it) + d = pickle.dumps(it) + it = pickle.loads(d) + values = list(it) + [drop] + self.assertEqual(sorted(values), sorted(list(data.values()))) from test import mapping_tests diff --git a/Lib/test/test_enumerate.py b/Lib/test/test_enumerate.py --- a/Lib/test/test_enumerate.py +++ b/Lib/test/test_enumerate.py @@ -1,5 +1,6 @@ import unittest import sys +import pickle from test import support @@ -61,7 +62,25 @@ def __iter__(self): return self -class EnumerateTestCase(unittest.TestCase): +class PickleTest: + # Helper to check picklability + def check_pickle(self, itorg, seq): + d = pickle.dumps(itorg) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), seq) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + self.assertFalse(seq[1:]) + return + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), seq[1:]) + +class EnumerateTestCase(unittest.TestCase, PickleTest): enum = enumerate seq, res = 'abc', [(0,'a'), (1,'b'), (2,'c')] @@ -73,6 +92,9 @@ self.assertEqual(list(self.enum(self.seq)), self.res) self.enum.__doc__ + def test_pickle(self): + self.check_pickle(self.enum(self.seq), self.res) + def test_getitemseqn(self): self.assertEqual(list(self.enum(G(self.seq))), self.res) e = self.enum(G('')) @@ -126,7 +148,7 @@ seq = range(10,20000,2) res = list(zip(range(20000), seq)) -class TestReversed(unittest.TestCase): +class TestReversed(unittest.TestCase, PickleTest): def test_simple(self): class A: @@ -212,6 +234,10 @@ ngi = NoGetItem() self.assertRaises(TypeError, reversed, ngi) + def test_pickle(self): + for data in 'abc', range(5), tuple(enumerate('abc')), range(1,17,5): + self.check_pickle(reversed(data), list(data)[::-1]) + class EnumerateStartTestCase(EnumerateTestCase): diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py --- a/Lib/test/test_iter.py +++ b/Lib/test/test_iter.py @@ -2,6 +2,8 @@ import unittest from test.support import run_unittest, TESTFN, unlink, cpython_only +import pickle +import collections.abc # Test result of triple loop (too big to inline) TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2), @@ -28,6 +30,8 @@ raise StopIteration self.i = res + 1 return res + def __iter__(self): + return self class IteratingSequenceClass: def __init__(self, n): @@ -49,7 +53,9 @@ class TestCase(unittest.TestCase): # Helper to check that an iterator returns a given sequence - def check_iterator(self, it, seq): + def check_iterator(self, it, seq, pickle=True): + if pickle: + self.check_pickle(it, seq) res = [] while 1: try: @@ -60,12 +66,33 @@ self.assertEqual(res, seq) # Helper to check that a for loop generates a given sequence - def check_for_loop(self, expr, seq): + def check_for_loop(self, expr, seq, pickle=True): + if pickle: + self.check_pickle(iter(expr), seq) res = [] for val in expr: res.append(val) self.assertEqual(res, seq) + # Helper to check picklability + def check_pickle(self, itorg, seq): + d = pickle.dumps(itorg) + it = pickle.loads(d) + # Cannot assert type equality because dict iterators unpickle as list + # iterators. + # self.assertEqual(type(itorg), type(it)) + self.assertTrue(isinstance(it, collections.abc.Iterator)) + self.assertEqual(list(it), seq) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + return + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), seq[1:]) + # Test basic use of iter() function def test_iter_basic(self): self.check_iterator(iter(range(10)), list(range(10))) @@ -138,7 +165,7 @@ if i > 100: raise IndexError # Emergency stop return i - self.check_iterator(iter(C(), 10), list(range(10))) + self.check_iterator(iter(C(), 10), list(range(10)), pickle=False) # Test two-argument iter() with function def test_iter_function(self): @@ -146,7 +173,7 @@ i = state[0] state[0] = i+1 return i - self.check_iterator(iter(spam, 10), list(range(10))) + self.check_iterator(iter(spam, 10), list(range(10)), pickle=False) # Test two-argument iter() with function that raises StopIteration def test_iter_function_stop(self): @@ -156,7 +183,7 @@ raise StopIteration state[0] = i+1 return i - self.check_iterator(iter(spam, 20), list(range(10))) + self.check_iterator(iter(spam, 20), list(range(10)), pickle=False) # Test exception propagation through function iterator def test_exception_function(self): @@ -198,7 +225,7 @@ if i == 10: raise StopIteration return SequenceClass.__getitem__(self, i) - self.check_for_loop(MySequenceClass(20), list(range(10))) + self.check_for_loop(MySequenceClass(20), list(range(10)), pickle=False) # Test a big range def test_iter_big_range(self): @@ -237,8 +264,8 @@ f.close() f = open(TESTFN, "r") try: - self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"]) - self.check_for_loop(f, []) + self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"], pickle=False) + self.check_for_loop(f, [], pickle=False) finally: f.close() try: 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 @@ -37,6 +37,13 @@ 'Test predicate' return x%2==1 +def tupleize(*args): + return args + +def irange(n): + for i in range(n): + yield i + class StopNow: 'Class emulating an empty iterable.' def __iter__(self): @@ -55,8 +62,59 @@ 'Factorial' return prod(range(1, n+1)) +# root level methods for pickling ability +def testR(r): + return r[0] + +def testR2(r): + return r[2] + +def underten(x): + return x<10 + class TestBasicOps(unittest.TestCase): + def pickletest(self, it, stop=4, take=1, compare=None): + """Test that an iterator is the same after pickling, also when part-consumed""" + def expand(it, i=0): + # Recursively expand iterables, within sensible bounds + if i > 10: + raise RuntimeError("infinite recursion encountered") + if isinstance(it, str): + return it + try: + l = list(islice(it, stop)) + except TypeError: + return it # can't expand it + return [expand(e, i+1) for e in l] + + # Test the initial copy against the original + dump = pickle.dumps(it) + i2 = pickle.loads(dump) + self.assertEqual(type(it), type(i2)) + a, b = expand(it), expand(i2) + self.assertEqual(a, b) + if compare: + c = expand(compare) + self.assertEqual(a, c) + + # Take from the copy, and create another copy and compare them. + i3 = pickle.loads(dump) + took = 0 + try: + for i in range(take): + next(i3) + took += 1 + except StopIteration: + pass #in case there is less data than 'take' + dump = pickle.dumps(i3) + i4 = pickle.loads(dump) + a, b = expand(i3), expand(i4) + self.assertEqual(a, b) + if compare: + c = expand(compare[took:]) + self.assertEqual(a, c); + def test_accumulate(self): self.assertEqual(list(accumulate(range(10))), # one positional arg [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]) @@ -83,6 +141,7 @@ [2, 16, 144, 720, 5040, 0, 0, 0, 0, 0]) with self.assertRaises(TypeError): list(accumulate(s, chr)) # unary-operation + self.pickletest(accumulate(range(10))) # test pickling def test_chain(self): @@ -106,14 +165,43 @@ self.assertEqual(take(4, chain.from_iterable(['abc', 'def'])), list('abcd')) self.assertRaises(TypeError, list, chain.from_iterable([2, 3])) + def test_chain_reducible(self): + operators = [copy.deepcopy, + lambda s: pickle.loads(pickle.dumps(s))] + for oper in operators: + it = chain('abc', 'def') + self.assertEqual(list(oper(it)), list('abcdef')) + self.assertEqual(next(it), 'a') + self.assertEqual(list(oper(it)), list('bcdef')) + + self.assertEqual(list(oper(chain(''))), []) + self.assertEqual(take(4, oper(chain('abc', 'def'))), list('abcd')) + self.assertRaises(TypeError, list, oper(chain(2, 3))) + self.pickletest(chain('abc', 'def'), compare=list('abcdef')) + def test_combinations(self): self.assertRaises(TypeError, combinations, 'abc') # missing r argument self.assertRaises(TypeError, combinations, 'abc', 2, 1) # too many arguments self.assertRaises(TypeError, combinations, None) # pool is not iterable self.assertRaises(ValueError, combinations, 'abc', -2) # r is negative - self.assertEqual(list(combinations('abc', 32)), []) # r > n - self.assertEqual(list(combinations(range(4), 3)), - [(0,1,2), (0,1,3), (0,2,3), (1,2,3)]) + + for op in (lambda a:a, lambda a:pickle.loads(pickle.dumps(a))): + self.assertEqual(list(op(combinations('abc', 32))), []) # r > n + + self.assertEqual(list(op(combinations('ABCD', 2))), + [('A','B'), ('A','C'), ('A','D'), ('B','C'), ('B','D'), ('C','D')]) + testIntermediate = combinations('ABCD', 2) + next(testIntermediate) + self.assertEqual(list(op(testIntermediate)), + [('A','C'), ('A','D'), ('B','C'), ('B','D'), ('C','D')]) + + self.assertEqual(list(op(combinations(range(4), 3))), + [(0,1,2), (0,1,3), (0,2,3), (1,2,3)]) + testIntermediate = combinations(range(4), 3) + next(testIntermediate) + self.assertEqual(list(op(testIntermediate)), + [(0,1,3), (0,2,3), (1,2,3)]) + def combinations1(iterable, r): 'Pure python version shown in the docs' @@ -168,6 +256,9 @@ self.assertEqual(result, list(combinations2(values, r))) # matches second pure python version self.assertEqual(result, list(combinations3(values, r))) # matches second pure python version + self.pickletest(combinations(values, r)) # test pickling + + # Test implementation detail: tuple re-use @support.impl_detail("tuple reuse is specific to CPython") def test_combinations_tuple_reuse(self): self.assertEqual(len(set(map(id, combinations('abcde', 3)))), 1) @@ -179,8 +270,15 @@ self.assertRaises(TypeError, cwr, 'abc', 2, 1) # too many arguments self.assertRaises(TypeError, cwr, None) # pool is not iterable self.assertRaises(ValueError, cwr, 'abc', -2) # r is negative - self.assertEqual(list(cwr('ABC', 2)), - [('A','A'), ('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')]) + + for op in (lambda a:a, lambda a:pickle.loads(pickle.dumps(a))): + self.assertEqual(list(op(cwr('ABC', 2))), + [('A','A'), ('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')]) + testIntermediate = cwr('ABC', 2) + next(testIntermediate) + self.assertEqual(list(op(testIntermediate)), + [('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')]) + def cwr1(iterable, r): 'Pure python version shown in the docs' @@ -239,6 +337,10 @@ self.assertEqual(result, list(cwr1(values, r))) # matches first pure python version self.assertEqual(result, list(cwr2(values, r))) # matches second pure python version + self.pickletest(cwr(values,r)) # test pickling + + # Test implementation detail: tuple re-use + @support.impl_detail("tuple reuse is specific to CPython") def test_combinations_with_replacement_tuple_reuse(self): cwr = combinations_with_replacement @@ -305,6 +407,8 @@ self.assertEqual(result, list(permutations(values, None))) # test r as None self.assertEqual(result, list(permutations(values))) # test default r + self.pickletest(permutations(values, r)) # test pickling + @support.impl_detail("tuple resuse is CPython specific") def test_permutations_tuple_reuse(self): self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1) @@ -359,6 +463,24 @@ self.assertRaises(TypeError, compress, range(6)) # too few args self.assertRaises(TypeError, compress, range(6), None) # too many args + # check copy, deepcopy, pickle + for op in (lambda a:copy.copy(a), lambda a:copy.deepcopy(a), lambda a:pickle.loads(pickle.dumps(a))): + for data, selectors, result1, result2 in [ + ('ABCDEF', [1,0,1,0,1,1], 'ACEF', 'CEF'), + ('ABCDEF', [0,0,0,0,0,0], '', ''), + ('ABCDEF', [1,1,1,1,1,1], 'ABCDEF', 'BCDEF'), + ('ABCDEF', [1,0,1], 'AC', 'C'), + ('ABC', [0,1,1,1,1,1], 'BC', 'C'), + ]: + + self.assertEqual(list(op(compress(data=data, selectors=selectors))), list(result1)) + self.assertEqual(list(op(compress(data, selectors))), list(result1)) + testIntermediate = compress(data, selectors) + if result1: + next(testIntermediate) + self.assertEqual(list(op(testIntermediate)), list(result2)) + + def test_count(self): self.assertEqual(lzip('abc',count()), [('a', 0), ('b', 1), ('c', 2)]) self.assertEqual(lzip('abc',count(3)), [('a', 3), ('b', 4), ('c', 5)]) @@ -393,7 +515,7 @@ c = count(value) self.assertEqual(next(copy.copy(c)), value) self.assertEqual(next(copy.deepcopy(c)), value) - self.assertEqual(next(pickle.loads(pickle.dumps(c))), value) + self.pickletest(count(value)) #check proper internal error handling for large "step' sizes count(1, maxsize+5); sys.exc_info() @@ -440,6 +562,7 @@ else: r2 = ('count(%r, %r)' % (i, j)).replace('L', '') self.assertEqual(r1, r2) + self.pickletest(count(i, j)) def test_cycle(self): self.assertEqual(take(10, cycle('abc')), list('abcabcabca')) @@ -448,6 +571,18 @@ self.assertRaises(TypeError, cycle, 5) self.assertEqual(list(islice(cycle(gen3()),10)), [0,1,2,0,1,2,0,1,2,0]) + # check copy, deepcopy, pickle + c = cycle('abc') + self.assertEqual(next(c), 'a') + #simple copy currently not supported, because __reduce__ returns + #an internal iterator + #self.assertEqual(take(10, copy.copy(c)), list('bcabcabcab')) + self.assertEqual(take(10, copy.deepcopy(c)), list('bcabcabcab')) + self.assertEqual(take(10, pickle.loads(pickle.dumps(c))), list('bcabcabcab')) + next(c) + self.assertEqual(take(10, pickle.loads(pickle.dumps(c))), list('cabcabcabc')) + self.pickletest(cycle('abc')) + def test_groupby(self): # Check whether it accepts arguments correctly self.assertEqual([], list(groupby([]))) @@ -466,18 +601,37 @@ dup.append(elem) self.assertEqual(s, dup) + # Check normal pickled + dup = [] + for k, g in pickle.loads(pickle.dumps(groupby(s, testR))): + for elem in g: + self.assertEqual(k, elem[0]) + dup.append(elem) + self.assertEqual(s, dup) + # Check nested case dup = [] - for k, g in groupby(s, lambda r:r[0]): - for ik, ig in groupby(g, lambda r:r[2]): + for k, g in groupby(s, testR): + for ik, ig in groupby(g, testR2): for elem in ig: self.assertEqual(k, elem[0]) self.assertEqual(ik, elem[2]) dup.append(elem) self.assertEqual(s, dup) + # Check nested and pickled + dup = [] + for k, g in pickle.loads(pickle.dumps(groupby(s, testR))): + for ik, ig in pickle.loads(pickle.dumps(groupby(g, testR2))): + for elem in ig: + self.assertEqual(k, elem[0]) + self.assertEqual(ik, elem[2]) + dup.append(elem) + self.assertEqual(s, dup) + + # Check case where inner iterator is not used - keys = [k for k, g in groupby(s, lambda r:r[0])] + keys = [k for k, g in groupby(s, testR)] expectedkeys = set([r[0] for r in s]) self.assertEqual(set(keys), expectedkeys) self.assertEqual(len(keys), len(expectedkeys)) @@ -548,6 +702,20 @@ self.assertRaises(TypeError, filter, isEven, 3) self.assertRaises(TypeError, next, filter(range(6), range(6))) + # check copy, deepcopy, pickle + ans = [0,2,4] + + c = filter(isEven, range(6)) + self.assertEqual(list(copy.copy(c)), ans) + c = filter(isEven, range(6)) + self.assertEqual(list(copy.deepcopy(c)), ans) + c = filter(isEven, range(6)) + self.assertEqual(list(pickle.loads(pickle.dumps(c))), ans) + next(c) + self.assertEqual(list(pickle.loads(pickle.dumps(c))), ans[1:]) + c = filter(isEven, range(6)) + self.pickletest(c) + def test_filterfalse(self): self.assertEqual(list(filterfalse(isEven, range(6))), [1,3,5]) self.assertEqual(list(filterfalse(None, [0,1,0,2,0])), [0,0,0]) @@ -558,6 +726,7 @@ self.assertRaises(TypeError, filterfalse, lambda x:x, range(6), 7) self.assertRaises(TypeError, filterfalse, isEven, 3) self.assertRaises(TypeError, next, filterfalse(range(6), range(6))) + self.pickletest(filterfalse(isEven, range(6))) def test_zip(self): # XXX This is rather silly now that builtin zip() calls zip()... @@ -582,6 +751,23 @@ ids = list(map(id, list(zip('abc', 'def')))) self.assertEqual(len(dict.fromkeys(ids)), len(ids)) + # check copy, deepcopy, pickle + ans = [(x,y) for x, y in copy.copy(zip('abc',count()))] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + + ans = [(x,y) for x, y in copy.deepcopy(zip('abc',count()))] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + + ans = [(x,y) for x, y in pickle.loads(pickle.dumps(zip('abc',count())))] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + + testIntermediate = zip('abc',count()) + next(testIntermediate) + ans = [(x,y) for x, y in pickle.loads(pickle.dumps(testIntermediate))] + self.assertEqual(ans, [('b', 1), ('c', 2)]) + + self.pickletest(zip('abc', count())) + def test_ziplongest(self): for args in [ ['abc', range(6)], @@ -631,6 +817,12 @@ ids = list(map(id, list(zip_longest('abc', 'def')))) self.assertEqual(len(dict.fromkeys(ids)), len(ids)) + def test_zip_longest_pickling(self): + self.pickletest(zip_longest("abc", "def")) + self.pickletest(zip_longest("abc", "defgh")) + self.pickletest(zip_longest("abc", "defgh", fillvalue=1)) + self.pickletest(zip_longest("", "defgh")) + def test_bug_7244(self): class Repeater: @@ -734,6 +926,20 @@ self.assertEqual(len(set(map(id, product('abc', 'def')))), 1) self.assertNotEqual(len(set(map(id, list(product('abc', 'def'))))), 1) + def test_product_pickling(self): + # check copy, deepcopy, pickle + for args, result in [ + ([], [()]), # zero iterables + (['ab'], [('a',), ('b',)]), # one iterable + ([range(2), range(3)], [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2)]), # two iterables + ([range(0), range(2), range(3)], []), # first iterable with zero length + ([range(2), range(0), range(3)], []), # middle iterable with zero length + ([range(2), range(3), range(0)], []), # last iterable with zero length + ]: + self.assertEqual(list(copy.copy(product(*args))), result) + self.assertEqual(list(copy.deepcopy(product(*args))), result) + self.pickletest(product(*args)) + def test_repeat(self): self.assertEqual(list(repeat(object='a', times=3)), ['a', 'a', 'a']) self.assertEqual(lzip(range(3),repeat('a')), @@ -752,11 +958,16 @@ list(r) self.assertEqual(repr(r), 'repeat((1+0j), 0)') + # check copy, deepcopy, pickle + c = repeat(object='a', times=10) + self.assertEqual(next(c), 'a') + self.assertEqual(take(2, copy.copy(c)), list('a' * 2)) + self.assertEqual(take(2, copy.deepcopy(c)), list('a' * 2)) + self.pickletest(repeat(object='a', times=10)) + def test_map(self): self.assertEqual(list(map(operator.pow, range(3), range(1,7))), [0**1, 1**2, 2**3]) - def tupleize(*args): - return args self.assertEqual(list(map(tupleize, 'abc', range(5))), [('a',0),('b',1),('c',2)]) self.assertEqual(list(map(tupleize, 'abc', count())), @@ -771,6 +982,18 @@ self.assertRaises(ValueError, next, map(errfunc, [4], [5])) self.assertRaises(TypeError, next, map(onearg, [4], [5])) + # check copy, deepcopy, pickle + ans = [('a',0),('b',1),('c',2)] + + c = map(tupleize, 'abc', count()) + self.assertEqual(list(copy.copy(c)), ans) + + c = map(tupleize, 'abc', count()) + self.assertEqual(list(copy.deepcopy(c)), ans) + + c = map(tupleize, 'abc', count()) + self.pickletest(c) + def test_starmap(self): self.assertEqual(list(starmap(operator.pow, zip(range(3), range(1,7)))), [0**1, 1**2, 2**3]) @@ -785,6 +1008,18 @@ self.assertRaises(ValueError, next, starmap(errfunc, [(4,5)])) self.assertRaises(TypeError, next, starmap(onearg, [(4,5)])) + # check copy, deepcopy, pickle + ans = [0**1, 1**2, 2**3] + + c = starmap(operator.pow, zip(range(3), range(1,7))) + self.assertEqual(list(copy.copy(c)), ans) + + c = starmap(operator.pow, zip(range(3), range(1,7))) + self.assertEqual(list(copy.deepcopy(c)), ans) + + c = starmap(operator.pow, zip(range(3), range(1,7))) + self.pickletest(c) + def test_islice(self): for args in [ # islice(args) should agree with range(args) (10, 20, 3), @@ -817,17 +1052,18 @@ self.assertEqual(list(it), list(range(3, 10))) # Test invalid arguments - self.assertRaises(TypeError, islice, range(10)) - self.assertRaises(TypeError, islice, range(10), 1, 2, 3, 4) - self.assertRaises(ValueError, islice, range(10), -5, 10, 1) - self.assertRaises(ValueError, islice, range(10), 1, -5, -1) - self.assertRaises(ValueError, islice, range(10), 1, 10, -1) - self.assertRaises(ValueError, islice, range(10), 1, 10, 0) - self.assertRaises(ValueError, islice, range(10), 'a') - self.assertRaises(ValueError, islice, range(10), 'a', 1) - self.assertRaises(ValueError, islice, range(10), 1, 'a') - self.assertRaises(ValueError, islice, range(10), 'a', 1, 1) - self.assertRaises(ValueError, islice, range(10), 1, 'a', 1) + ra = range(10) + self.assertRaises(TypeError, islice, ra) + self.assertRaises(TypeError, islice, ra, 1, 2, 3, 4) + self.assertRaises(ValueError, islice, ra, -5, 10, 1) + self.assertRaises(ValueError, islice, ra, 1, -5, -1) + self.assertRaises(ValueError, islice, ra, 1, 10, -1) + self.assertRaises(ValueError, islice, ra, 1, 10, 0) + self.assertRaises(ValueError, islice, ra, 'a') + self.assertRaises(ValueError, islice, ra, 'a', 1) + self.assertRaises(ValueError, islice, ra, 1, 'a') + self.assertRaises(ValueError, islice, ra, 'a', 1, 1) + self.assertRaises(ValueError, islice, ra, 1, 'a', 1) self.assertEqual(len(list(islice(count(), 1, 10, maxsize))), 1) # Issue #10323: Less islice in a predictable state @@ -835,9 +1071,22 @@ self.assertEqual(list(islice(c, 1, 3, 50)), [1]) self.assertEqual(next(c), 3) + # check copy, deepcopy, pickle + for args in [ # islice(args) should agree with range(args) + (10, 20, 3), + (10, 3, 20), + (10, 20), + (10, 3), + (20,) + ]: + self.assertEqual(list(copy.copy(islice(range(100), *args))), + list(range(*args))) + self.assertEqual(list(copy.deepcopy(islice(range(100), *args))), + list(range(*args))) + self.pickletest(islice(range(100), *args)) + def test_takewhile(self): data = [1, 3, 5, 20, 2, 4, 6, 8] - underten = lambda x: x<10 self.assertEqual(list(takewhile(underten, data)), [1, 3, 5]) self.assertEqual(list(takewhile(underten, [])), []) self.assertRaises(TypeError, takewhile) @@ -849,9 +1098,14 @@ self.assertEqual(list(t), [1, 1, 1]) self.assertRaises(StopIteration, next, t) + # check copy, deepcopy, pickle + self.assertEqual(list(copy.copy(takewhile(underten, data))), [1, 3, 5]) + self.assertEqual(list(copy.deepcopy(takewhile(underten, data))), + [1, 3, 5]) + self.pickletest(takewhile(underten, data)) + def test_dropwhile(self): data = [1, 3, 5, 20, 2, 4, 6, 8] - underten = lambda x: x<10 self.assertEqual(list(dropwhile(underten, data)), [20, 2, 4, 6, 8]) self.assertEqual(list(dropwhile(underten, [])), []) self.assertRaises(TypeError, dropwhile) @@ -860,11 +1114,14 @@ self.assertRaises(TypeError, next, dropwhile(10, [(4,5)])) self.assertRaises(ValueError, next, dropwhile(errfunc, [(4,5)])) + # check copy, deepcopy, pickle + self.assertEqual(list(copy.copy(dropwhile(underten, data))), [20, 2, 4, 6, 8]) + self.assertEqual(list(copy.deepcopy(dropwhile(underten, data))), + [20, 2, 4, 6, 8]) + self.pickletest(dropwhile(underten, data)) + def test_tee(self): n = 200 - def irange(n): - for i in range(n): - yield i a, b = tee([]) # test empty iterator self.assertEqual(list(a), []) @@ -949,6 +1206,67 @@ del a self.assertRaises(ReferenceError, getattr, p, '__class__') + ans = list('abc') + long_ans = list(range(10000)) + + # check copy + a, b = tee('abc') + self.assertEqual(list(copy.copy(a)), ans) + self.assertEqual(list(copy.copy(b)), ans) + a, b = tee(list(range(10000))) + self.assertEqual(list(copy.copy(a)), long_ans) + self.assertEqual(list(copy.copy(b)), long_ans) + + # check partially consumed copy + a, b = tee('abc') + take(2, a) + take(1, b) + self.assertEqual(list(copy.copy(a)), ans[2:]) + self.assertEqual(list(copy.copy(b)), ans[1:]) + self.assertEqual(list(a), ans[2:]) + self.assertEqual(list(b), ans[1:]) + a, b = tee(range(10000)) + take(100, a) + take(60, b) + self.assertEqual(list(copy.copy(a)), long_ans[100:]) + self.assertEqual(list(copy.copy(b)), long_ans[60:]) + self.assertEqual(list(a), long_ans[100:]) + self.assertEqual(list(b), long_ans[60:]) + + # check deepcopy + a, b = tee('abc') + self.assertEqual(list(copy.deepcopy(a)), ans) + self.assertEqual(list(copy.deepcopy(b)), ans) + self.assertEqual(list(a), ans) + self.assertEqual(list(b), ans) + a, b = tee(range(10000)) + self.assertEqual(list(copy.deepcopy(a)), long_ans) + self.assertEqual(list(copy.deepcopy(b)), long_ans) + self.assertEqual(list(a), long_ans) + self.assertEqual(list(b), long_ans) + + # check partially consumed deepcopy + a, b = tee('abc') + take(2, a) + take(1, b) + self.assertEqual(list(copy.deepcopy(a)), ans[2:]) + self.assertEqual(list(copy.deepcopy(b)), ans[1:]) + self.assertEqual(list(a), ans[2:]) + self.assertEqual(list(b), ans[1:]) + a, b = tee(range(10000)) + take(100, a) + take(60, b) + self.assertEqual(list(copy.deepcopy(a)), long_ans[100:]) + self.assertEqual(list(copy.deepcopy(b)), long_ans[60:]) + self.assertEqual(list(a), long_ans[100:]) + self.assertEqual(list(b), long_ans[60:]) + + # check pickle + self.pickletest(iter(tee('abc'))) + a, b = tee('abc') + self.pickletest(a, compare=ans) + self.pickletest(b, compare=ans) + def test_StopIteration(self): self.assertRaises(StopIteration, next, zip()) @@ -974,9 +1292,21 @@ class TestExamples(unittest.TestCase): - def test_accumlate(self): + def test_accumulate(self): self.assertEqual(list(accumulate([1,2,3,4,5])), [1, 3, 6, 10, 15]) + def test_accumulate_reducible(self): + # check copy, deepcopy, pickle + data = [1, 2, 3, 4, 5] + accumulated = [1, 3, 6, 10, 15] + it = accumulate(data) + + self.assertEqual(list(pickle.loads(pickle.dumps(it))), accumulated[:]) + self.assertEqual(next(it), 1) + self.assertEqual(list(pickle.loads(pickle.dumps(it))), accumulated[1:]) + self.assertEqual(list(copy.deepcopy(it)), accumulated[1:]) + self.assertEqual(list(copy.copy(it)), accumulated[1:]) + def test_chain(self): self.assertEqual(''.join(chain('ABC', 'DEF')), 'ABCDEF') diff --git a/Lib/test/test_list.py b/Lib/test/test_list.py --- a/Lib/test/test_list.py +++ b/Lib/test/test_list.py @@ -1,5 +1,6 @@ import sys from test import support, list_tests +import pickle class ListTest(list_tests.CommonTest): type2test = list @@ -69,6 +70,33 @@ check(10) # check our checking code check(1000000) + def test_iterator_pickle(self): + # Userlist iterators don't support pickling yet since + # they are based on generators. + data = self.type2test([4, 5, 6, 7]) + it = itorg = iter(data) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(self.type2test(it), self.type2test(data)) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(self.type2test(it), self.type2test(data)[1:]) + + def test_reversed_pickle(self): + data = self.type2test([4, 5, 6, 7]) + it = itorg = reversed(data) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(self.type2test(it), self.type2test(reversed(data))) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(self.type2test(it), self.type2test(reversed(data))[1:]) def test_main(verbose=None): support.run_unittest(ListTest) diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -341,13 +341,35 @@ def test_pickling(self): testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1), - (13, 21, 3), (-2, 2, 2)] + (13, 21, 3), (-2, 2, 2), (2**65, 2**65+2)] for proto in range(pickle.HIGHEST_PROTOCOL + 1): for t in testcases: r = range(*t) self.assertEqual(list(pickle.loads(pickle.dumps(r, proto))), list(r)) + def test_iterator_pickling(self): + testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1), + (13, 21, 3), (-2, 2, 2), (2**65, 2**65+2)] + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + for t in testcases: + it = itorg = iter(range(*t)) + data = list(range(*t)) + + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), data) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + continue + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), data[1:]) + def test_odd_bug(self): # This used to raise a "SystemError: NULL result without error" # because the range validation step was eating the exception 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 @@ -9,6 +9,7 @@ import sys import warnings import collections +import collections.abc class PassThru(Exception): pass @@ -234,6 +235,26 @@ dup = pickle.loads(p) self.assertEqual(self.s.x, dup.x) + def test_iterator_pickling(self): + itorg = iter(self.s) + data = self.thetype(self.s) + d = pickle.dumps(itorg) + it = pickle.loads(d) + # Set iterators unpickle as list iterators due to the + # undefined order of set items. + # self.assertEqual(type(itorg), type(it)) + self.assertTrue(isinstance(it, collections.abc.Iterator)) + self.assertEqual(self.thetype(it), data) + + it = pickle.loads(d) + try: + drop = next(it) + except StopIteration: + return + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(self.thetype(it), data - self.thetype((drop,))) + def test_deepcopy(self): class Tracer: def __init__(self, value): diff --git a/Lib/test/test_tuple.py b/Lib/test/test_tuple.py --- a/Lib/test/test_tuple.py +++ b/Lib/test/test_tuple.py @@ -1,6 +1,7 @@ from test import support, seq_tests import gc +import pickle class TupleTest(seq_tests.CommonTest): type2test = tuple @@ -164,6 +165,34 @@ check(10) # check our checking code check(1000000) + def test_iterator_pickle(self): + # Userlist iterators don't support pickling yet since + # they are based on generators. + data = self.type2test([4, 5, 6, 7]) + itorg = iter(data) + d = pickle.dumps(itorg) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(self.type2test(it), self.type2test(data)) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(self.type2test(it), self.type2test(data)[1:]) + + def test_reversed_pickle(self): + data = self.type2test([4, 5, 6, 7]) + itorg = reversed(data) + d = pickle.dumps(itorg) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(self.type2test(it), self.type2test(reversed(data))) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(self.type2test(it), self.type2test(reversed(data))[1:]) + def test_main(): support.run_unittest(TupleTest) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1122,6 +1122,35 @@ } static PyObject * +dequeiter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + Py_ssize_t i, index=0; + PyObject *deque; + dequeiterobject *it; + if (!PyArg_ParseTuple(args, "O!|n", &deque_type, &deque, &index)) + return NULL; + assert(type == &dequeiter_type); + + it = (dequeiterobject*)deque_iter((dequeobject *)deque); + if (!it) + return NULL; + /* consume items from the queue */ + for(i=0; icounter) { + Py_DECREF(it); + return NULL; + } else + break; + } + } + return (PyObject*)it; +} + +static PyObject * dequeiter_len(dequeiterobject *it) { return PyLong_FromSsize_t(it->counter); @@ -1129,14 +1158,21 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +dequeiter_reduce(dequeiterobject *it) +{ + return Py_BuildValue("O(On)", Py_TYPE(it), it->deque, it->deque->len - it->counter); +} + static PyMethodDef dequeiter_methods[] = { {"__length_hint__", (PyCFunction)dequeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)dequeiter_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; static PyTypeObject dequeiter_type = { PyVarObject_HEAD_INIT(NULL, 0) - "deque_iterator", /* tp_name */ + "_collections._deque_iterator", /* tp_name */ sizeof(dequeiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -1164,6 +1200,16 @@ PyObject_SelfIter, /* tp_iter */ (iternextfunc)dequeiter_next, /* tp_iternext */ dequeiter_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 */ + dequeiter_new, /* tp_new */ 0, }; @@ -1217,9 +1263,38 @@ return item; } +static PyObject * +dequereviter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + Py_ssize_t i, index=0; + PyObject *deque; + dequeiterobject *it; + if (!PyArg_ParseTuple(args, "O!|n", &deque_type, &deque, &index)) + return NULL; + assert(type == &dequereviter_type); + + it = (dequeiterobject*)deque_reviter((dequeobject *)deque); + if (!it) + return NULL; + /* consume items from the queue */ + for(i=0; icounter) { + Py_DECREF(it); + return NULL; + } else + break; + } + } + return (PyObject*)it; +} + static PyTypeObject dequereviter_type = { PyVarObject_HEAD_INIT(NULL, 0) - "deque_reverse_iterator", /* tp_name */ + "_collections._deque_reverse_iterator", /* tp_name */ sizeof(dequeiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -1247,6 +1322,16 @@ PyObject_SelfIter, /* tp_iter */ (iternextfunc)dequereviter_next, /* tp_iternext */ dequeiter_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 */ + dequereviter_new, /* tp_new */ 0, }; @@ -1653,9 +1738,13 @@ if (PyType_Ready(&dequeiter_type) < 0) return NULL; + Py_INCREF(&dequeiter_type); + PyModule_AddObject(m, "_deque_iterator", (PyObject *)&dequeiter_type); if (PyType_Ready(&dequereviter_type) < 0) return NULL; + Py_INCREF(&dequereviter_type); + PyModule_AddObject(m, "_deque_reverse_iterator", (PyObject *)&dequereviter_type); return m; } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2753,6 +2753,34 @@ return 0; } +static PyObject * +arrayiter_reduce(arrayiterobject *it) +{ + return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + it->ao, it->index); +} + +static PyObject * +arrayiter_setstate(arrayiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); +static PyMethodDef arrayiter_methods[] = { + {"__reduce__", (PyCFunction)arrayiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)arrayiter_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + static PyTypeObject PyArrayIter_Type = { PyVarObject_HEAD_INIT(NULL, 0) "arrayiterator", /* tp_name */ @@ -2782,7 +2810,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)arrayiter_next, /* tp_iternext */ - 0, /* tp_methods */ + arrayiter_methods, /* tp_methods */ }; diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -134,6 +134,53 @@ return r; } +static PyObject * +groupby_reduce(groupbyobject *lz) +{ + /* reduce as a 'new' call with an optional 'setstate' if groupby + * has started + */ + PyObject *value; + if (lz->tgtkey && lz->currkey && lz->currvalue) + value = Py_BuildValue("O(OO)(OOO)", Py_TYPE(lz), + lz->it, lz->keyfunc, lz->currkey, lz->currvalue, lz->tgtkey); + else + value = Py_BuildValue("O(OO)", Py_TYPE(lz), + lz->it, lz->keyfunc); + + return value; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +groupby_setstate(groupbyobject *lz, PyObject *state) +{ + PyObject *currkey, *currvalue, *tgtkey; + if (!PyArg_ParseTuple(state, "OOO", &currkey, &currvalue, &tgtkey)) + return NULL; + Py_CLEAR(lz->currkey); + lz->currkey = currkey; + Py_INCREF(lz->currkey); + Py_CLEAR(lz->currvalue); + lz->currvalue = currvalue; + Py_INCREF(lz->currvalue); + Py_CLEAR(lz->tgtkey); + lz->tgtkey = tgtkey; + Py_INCREF(lz->tgtkey); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + +static PyMethodDef groupby_methods[] = { + {"__reduce__", (PyCFunction)groupby_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)groupby_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(groupby_doc, "groupby(iterable[, keyfunc]) -> create an iterator which returns\n\ (key, sub-iterator) grouped by each value of key(value).\n"); @@ -168,7 +215,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)groupby_next, /* tp_iternext */ - 0, /* tp_methods */ + groupby_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -194,6 +241,17 @@ static PyTypeObject _grouper_type; static PyObject * +_grouper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *parent, *tgtkey; + + if (!PyArg_ParseTuple(args, "O!O", &groupby_type, &parent, &tgtkey)) + return NULL; + + return _grouper_create((groupbyobject*) parent, tgtkey); +} + +static PyObject * _grouper_create(groupbyobject *parent, PyObject *tgtkey) { _grouperobject *igo; @@ -269,6 +327,20 @@ return r; } +static PyObject * +_grouper_reduce(_grouperobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), + lz->parent, lz->tgtkey); +} + +static PyMethodDef _grouper_methods[] = { + {"__reduce__", (PyCFunction)_grouper_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + + static PyTypeObject _grouper_type = { PyVarObject_HEAD_INIT(NULL, 0) "itertools._grouper", /* tp_name */ @@ -298,7 +370,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)_grouper_next, /* tp_iternext */ - 0, /* tp_methods */ + _grouper_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -308,7 +380,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - 0, /* tp_new */ + _grouper_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -344,7 +416,7 @@ static PyTypeObject teedataobject_type; static PyObject * -teedataobject_new(PyObject *it) +teedataobject_newinternal(PyObject *it) { teedataobject *tdo; @@ -364,7 +436,7 @@ teedataobject_jumplink(teedataobject *tdo) { if (tdo->nextlink == NULL) - tdo->nextlink = teedataobject_new(tdo->it); + tdo->nextlink = teedataobject_newinternal(tdo->it); Py_XINCREF(tdo->nextlink); return tdo->nextlink; } @@ -420,11 +492,80 @@ PyObject_GC_Del(tdo); } +static PyObject * +teedataobject_reduce(teedataobject *tdo) +{ + 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++) { + Py_INCREF(tdo->values[i]); + PyList_SET_ITEM(values, i, tdo->values[i]); + } + return Py_BuildValue("O(ONO)", Py_TYPE(tdo), tdo->it, + values, + tdo->nextlink ? tdo->nextlink : Py_None); +} + +static PyTypeObject teedataobject_type; + +static PyObject * +teedataobject_new(PyTypeObject *type, PyObject *args, PyObject *kw) +{ + teedataobject *tdo; + PyObject *it, *values, *next; + Py_ssize_t i, len; + + assert(type == &teedataobject_type); + if (!PyArg_ParseTuple(args, "OO!O", &it, &PyList_Type, &values, &next)) + return NULL; + + tdo = (teedataobject *)teedataobject_newinternal(it); + if (!tdo) + return NULL; + + len = PyList_GET_SIZE(values); + if (len > LINKCELLS) + goto err; + for (i=0; ivalues[i] = PyList_GET_ITEM(values, i); + Py_INCREF(tdo->values[i]); + } + tdo->numread = len; + + if (len == LINKCELLS) { + if (next != Py_None) { + if (Py_TYPE(next) != &teedataobject_type) + goto err; + assert(tdo->nextlink == NULL); + Py_INCREF(next); + tdo->nextlink = next; + } + } else { + if (next != Py_None) + goto err; /* shouldn't have a next if we are not full */ + } + return (PyObject*)tdo; + +err: + Py_XDECREF(tdo); + PyErr_SetString(PyExc_ValueError, "Invalid arguments"); + return NULL; +} + +static PyMethodDef teedataobject_methods[] = { + {"__reduce__", (PyCFunction)teedataobject_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + 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 */ - "itertools.tee_dataobject", /* tp_name */ + "itertools._tee_dataobject", /* tp_name */ sizeof(teedataobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -451,7 +592,7 @@ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + teedataobject_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -461,7 +602,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - 0, /* tp_new */ + teedataobject_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -528,7 +669,7 @@ to = PyObject_GC_New(teeobject, &tee_type); if (to == NULL) goto done; - to->dataobj = (teedataobject *)teedataobject_new(it); + to->dataobj = (teedataobject *)teedataobject_newinternal(it); if (!to->dataobj) { PyObject_GC_Del(to); to = NULL; @@ -548,7 +689,7 @@ { PyObject *iterable; - if (!PyArg_UnpackTuple(args, "tee", 1, 1, &iterable)) + if (!PyArg_UnpackTuple(args, "_tee", 1, 1, &iterable)) return NULL; return tee_fromiterable(iterable); } @@ -570,17 +711,43 @@ PyObject_GC_Del(to); } +static PyObject * +tee_reduce(teeobject *to) +{ + return Py_BuildValue("O(())(Oi)", Py_TYPE(to), to->dataobj, to->index); +} + +static PyObject * +tee_setstate(teeobject *to, PyObject *state) +{ + teedataobject *tdo; + int index; + if (!PyArg_ParseTuple(state, "O!i", &teedataobject_type, &tdo, &index)) + return NULL; + if (index < 0 || index > LINKCELLS) { + PyErr_SetString(PyExc_ValueError, "Index out of range"); + return NULL; + } + Py_CLEAR(to->dataobj); + to->dataobj = tdo; + Py_INCREF(to->dataobj); + to->index = index; + Py_RETURN_NONE; +} + PyDoc_STRVAR(teeobject_doc, "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}, {NULL, NULL} /* sentinel */ }; static PyTypeObject tee_type = { PyVarObject_HEAD_INIT(NULL, 0) - "itertools.tee", /* tp_name */ + "itertools._tee", /* tp_name */ sizeof(teeobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -771,6 +938,38 @@ } } +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); + } + +static PyObject * +cycle_setstate(cycleobject *lz, PyObject *state) +{ + PyObject *saved=NULL; + int firstpass; + if (!PyArg_ParseTuple(state, "Oi", &saved, &firstpass)) + return NULL; + Py_CLEAR(lz->saved); + lz->saved = saved; + Py_XINCREF(lz->saved); + lz->firstpass = firstpass != 0; + Py_RETURN_NONE; +} + +static PyMethodDef cycle_methods[] = { + {"__reduce__", (PyCFunction)cycle_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)cycle_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(cycle_doc, "cycle(iterable) --> cycle object\n\ \n\ @@ -807,7 +1006,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)cycle_next, /* tp_iternext */ - 0, /* tp_methods */ + cycle_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -913,6 +1112,31 @@ } } +static PyObject * +dropwhile_reduce(dropwhileobject *lz) +{ + return Py_BuildValue("O(OO)l", Py_TYPE(lz), + lz->func, lz->it, lz->start); +} + +static PyObject * +dropwhile_setstate(dropwhileobject *lz, PyObject *state) +{ + int start = PyObject_IsTrue(state); + if (start == -1) + return NULL; + lz->start = start; + Py_RETURN_NONE; +} + +static PyMethodDef dropwhile_methods[] = { + {"__reduce__", (PyCFunction)dropwhile_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)dropwhile_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(dropwhile_doc, "dropwhile(predicate, iterable) --> dropwhile object\n\ \n\ @@ -949,7 +1173,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)dropwhile_next, /* tp_iternext */ - 0, /* tp_methods */ + dropwhile_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1052,6 +1276,30 @@ return NULL; } +static PyObject * +takewhile_reduce(takewhileobject *lz) +{ + 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 == -1) + return NULL; + lz->stop = stop; + Py_RETURN_NONE; +} + +static PyMethodDef takewhile_reduce_methods[] = { + {"__reduce__", (PyCFunction)takewhile_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)takewhile_reduce_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; PyDoc_STRVAR(takewhile_doc, "takewhile(predicate, iterable) --> takewhile object\n\ \n\ @@ -1088,7 +1336,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)takewhile_next, /* tp_iternext */ - 0, /* tp_methods */ + takewhile_reduce_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1244,6 +1492,44 @@ return item; } +static PyObject * +islice_reduce(isliceobject *lz) +{ + /* When unpickled, generate a new object with the same bounds, + * then 'setstate' with the next and count + */ + PyObject *stop; + if (lz->stop == -1) { + stop = Py_None; + Py_INCREF(stop); + } else { + stop = PyLong_FromSsize_t(lz->stop); + if (stop == NULL) + return NULL; + } + return Py_BuildValue("O(OnNn)n", Py_TYPE(lz), + lz->it, lz->next, stop, lz->step, + lz->cnt); +} + +static PyObject * +islice_setstate(isliceobject *lz, PyObject *state) +{ + Py_ssize_t cnt = PyLong_AsSsize_t(state); + if (cnt == -1 && PyErr_Occurred()) + return NULL; + lz->cnt = cnt; + Py_RETURN_NONE; +} + +static PyMethodDef islice_methods[] = { + {"__reduce__", (PyCFunction)islice_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)islice_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(islice_doc, "islice(iterable, [start,] stop [, step]) --> islice object\n\ \n\ @@ -1284,7 +1570,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)islice_next, /* tp_iternext */ - 0, /* tp_methods */ + islice_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1379,6 +1665,19 @@ return result; } +static PyObject * +starmap_reduce(starmapobject *lz) +{ + /* Just pickle the iterator */ + return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->func, lz->it); +} + +static PyMethodDef starmap_methods[] = { + {"__reduce__", (PyCFunction)starmap_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(starmap_doc, "starmap(function, sequence) --> starmap object\n\ \n\ @@ -1415,7 +1714,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)starmap_next, /* tp_iternext */ - 0, /* tp_methods */ + starmap_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1534,6 +1833,41 @@ return chain_next(lz); /* recurse and use next active */ } +static PyObject * +chain_reduce(chainobject *lz) +{ + if (lz->source) { + /* we can't pickle function objects (itertools.from_iterable) so + * we must use setstate to replace the iterable. One day we + * will fix pickling of functions + */ + if (lz->active) { + return Py_BuildValue("O()(OO)", Py_TYPE(lz), lz->source, lz->active); + } else { + return Py_BuildValue("O()(O)", Py_TYPE(lz), lz->source); + } + } else { + return Py_BuildValue("O()", Py_TYPE(lz)); /* exhausted */ + } + return NULL; +} + +static PyObject * +chain_setstate(chainobject *lz, PyObject *state) +{ + PyObject *source, *active=NULL; + if (! PyArg_ParseTuple(state, "O|O", &source, &active)) + return NULL; + + Py_CLEAR(lz->source); + lz->source = source; + Py_INCREF(lz->source); + Py_CLEAR(lz->active); + lz->active = active; + Py_XINCREF(lz->active); + Py_RETURN_NONE; +} + PyDoc_STRVAR(chain_doc, "chain(*iterables) --> chain object\n\ \n\ @@ -1550,6 +1884,10 @@ static PyMethodDef chain_methods[] = { {"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, + setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -1790,6 +2128,83 @@ return NULL; } +static PyObject * +product_reduce(productobject *lz) +{ + if (lz->stopped) { + return Py_BuildValue("O(())", Py_TYPE(lz)); + } else if (lz->result == NULL) { + return Py_BuildValue("OO", Py_TYPE(lz), lz->pools); + } else { + PyObject *indices; + Py_ssize_t n, i; + + /* we must pickle the indices use them for setstate, and + * additionally indicate that the iterator has started + */ + n = PyTuple_GET_SIZE(lz->pools); + indices = PyTuple_New(n); + if (indices == NULL) + return NULL; + for (i=0; iindices[i]); + if (!index) { + Py_DECREF(indices); + return NULL; + } + PyTuple_SET_ITEM(indices, i, index); + } + return Py_BuildValue("OON", Py_TYPE(lz), lz->pools, indices); + } +} + +static PyObject * +product_setstate(productobject *lz, PyObject *state) +{ + PyObject *result; + Py_ssize_t n, i; + + n = PyTuple_GET_SIZE(lz->pools); + if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != n) { + PyErr_SetString(PyExc_ValueError, "invalid arguments"); + return NULL; + } + for (i=0; i n-1) + index = n-1; + lz->indices[i] = index; + } + + result = PyTuple_New(n); + if (!result) + return NULL; + for (i=0; ipools, i); + PyObject *element = PyTuple_GET_ITEM(pool, lz->indices[i]); + Py_INCREF(element); + PyTuple_SET_ITEM(result, i, element); + } + Py_CLEAR(lz->result); + lz->result = result; + Py_RETURN_NONE; +} + +static PyMethodDef product_methods[] = { + {"__reduce__", (PyCFunction)product_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)product_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(product_doc, "product(*iterables) --> product object\n\ \n\ @@ -1834,7 +2249,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)product_next, /* tp_iternext */ - 0, /* tp_methods */ + product_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2021,6 +2436,86 @@ return NULL; } +static PyObject * +combinations_reduce(combinationsobject *lz) +{ + if (lz->result == NULL) { + return Py_BuildValue("O(On)", Py_TYPE(lz), lz->pool, lz->r); + } else if (lz->stopped) { + return Py_BuildValue("O(()n)", Py_TYPE(lz), lz->r); + } else { + PyObject *indices; + Py_ssize_t i; + + /* we must pickle the indices and use them for setstate */ + indices = PyTuple_New(lz->r); + if (!indices) + return NULL; + for (i=0; ir; i++) + { + PyObject* index = PyLong_FromSsize_t(lz->indices[i]); + if (!index) { + Py_DECREF(indices); + return NULL; + } + PyTuple_SET_ITEM(indices, i, index); + } + + return Py_BuildValue("O(On)N", Py_TYPE(lz), lz->pool, lz->r, indices); + } +} + +static PyObject * +combinations_setstate(combinationsobject *lz, PyObject *state) +{ + PyObject *result; + Py_ssize_t i; + Py_ssize_t n = PyTuple_GET_SIZE(lz->pool); + + if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != lz->r) + { + PyErr_SetString(PyExc_ValueError, "invalid arguments"); + return NULL; + } + + 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; + /* clamp the index (beware of negative max) */ + if (index > max) + index = max; + if (index < 0) + index = 0; + lz->indices[i] = index; + } + + result = PyTuple_New(lz->r); + if (result == NULL) + return NULL; + for (i=0; ir; i++) { + PyObject *element = PyTuple_GET_ITEM(lz->pool, lz->indices[i]); + Py_INCREF(element); + PyTuple_SET_ITEM(result, i, element); + } + + Py_CLEAR(lz->result); + lz->result = result; + Py_RETURN_NONE; +} + +static PyMethodDef combinations_methods[] = { + {"__reduce__", (PyCFunction)combinations_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)combinations_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(combinations_doc, "combinations(iterable, r) --> combinations object\n\ \n\ @@ -2029,11 +2524,11 @@ static PyTypeObject combinations_type = { PyVarObject_HEAD_INIT(NULL, 0) - "itertools.combinations", /* tp_name */ + "itertools.combinations", /* tp_name */ sizeof(combinationsobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)combinations_dealloc, /* tp_dealloc */ + (destructor)combinations_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -2050,14 +2545,14 @@ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ - combinations_doc, /* tp_doc */ - (traverseproc)combinations_traverse, /* tp_traverse */ + combinations_doc, /* tp_doc */ + (traverseproc)combinations_traverse,/* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)combinations_next, /* tp_iternext */ - 0, /* tp_methods */ + (iternextfunc)combinations_next, /* tp_iternext */ + combinations_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2067,7 +2562,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - combinations_new, /* tp_new */ + combinations_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -2266,6 +2761,82 @@ return NULL; } +static PyObject * +cwr_reduce(cwrobject *lz) +{ + if (lz->result == NULL) { + return Py_BuildValue("O(On)", Py_TYPE(lz), lz->pool, lz->r); + } else if (lz->stopped) { + return Py_BuildValue("O(()n)", Py_TYPE(lz), lz->r); + } else { + PyObject *indices; + Py_ssize_t i; + + /* we must pickle the indices and use them for setstate */ + indices = PyTuple_New(lz->r); + if (!indices) + return NULL; + for (i=0; ir; i++) + { + PyObject* index = PyLong_FromSsize_t(lz->indices[i]); + if (!index) { + Py_DECREF(indices); + return NULL; + } + PyTuple_SET_ITEM(indices, i, index); + } + + return Py_BuildValue("O(On)N", Py_TYPE(lz), lz->pool, lz->r, indices); + } +} + +static PyObject * +cwr_setstate(cwrobject *lz, PyObject *state) +{ + PyObject *result; + Py_ssize_t n, i; + + if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != lz->r) + { + PyErr_SetString(PyExc_ValueError, "invalid arguments"); + return NULL; + } + + n = PyTuple_GET_SIZE(lz->pool); + 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 */ + if (index < 0) + index = 0; + else if (index > n-1) + index = n-1; + lz->indices[i] = index; + } + result = PyTuple_New(lz->r); + if (result == NULL) + return NULL; + for (i=0; ir; i++) { + PyObject *element = PyTuple_GET_ITEM(lz->pool, lz->indices[i]); + Py_INCREF(element); + PyTuple_SET_ITEM(result, i, element); + } + Py_CLEAR(lz->result); + lz->result = result; + Py_RETURN_NONE; +} + +static PyMethodDef cwr_methods[] = { + {"__reduce__", (PyCFunction)cwr_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)cwr_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(cwr_doc, "combinations_with_replacement(iterable, r) --> combinations_with_replacement object\n\ \n\ @@ -2275,11 +2846,11 @@ static PyTypeObject cwr_type = { PyVarObject_HEAD_INIT(NULL, 0) - "itertools.combinations_with_replacement", /* tp_name */ - sizeof(cwrobject), /* tp_basicsize */ + "itertools.combinations_with_replacement", /* tp_name */ + sizeof(cwrobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)cwr_dealloc, /* tp_dealloc */ + (destructor)cwr_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -2291,19 +2862,19 @@ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - cwr_doc, /* tp_doc */ - (traverseproc)cwr_traverse, /* tp_traverse */ + Py_TPFLAGS_BASETYPE, /* tp_flags */ + cwr_doc, /* tp_doc */ + (traverseproc)cwr_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)cwr_next, /* tp_iternext */ - 0, /* tp_methods */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)cwr_next, /* tp_iternext */ + cwr_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2313,8 +2884,8 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - cwr_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + cwr_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; @@ -2538,6 +3109,115 @@ return NULL; } +static PyObject * +permutations_reduce(permutationsobject *po) +{ + if (po->result == NULL) { + return Py_BuildValue("O(On)", Py_TYPE(po), po->pool, po->r); + } else if (po->stopped) { + return Py_BuildValue("O(()n)", Py_TYPE(po), po->r); + } else { + PyObject *indices=NULL, *cycles=NULL; + Py_ssize_t n, i; + + /* we must pickle the indices and cycles and use them for setstate */ + n = PyTuple_GET_SIZE(po->pool); + indices = PyTuple_New(n); + if (indices == NULL) + goto err; + for (i=0; iindices[i]); + if (!index) + goto err; + PyTuple_SET_ITEM(indices, i, index); + } + + cycles = PyTuple_New(po->r); + if (cycles == NULL) + goto err; + for (i=0; ir; i++) + { + PyObject* index = PyLong_FromSsize_t(po->cycles[i]); + if (!index) + goto err; + PyTuple_SET_ITEM(cycles, i, index); + } + return Py_BuildValue("O(On)(NN)", Py_TYPE(po), + po->pool, po->r, + indices, cycles); + err: + Py_XDECREF(indices); + Py_XDECREF(cycles); + return NULL; + } +} + +static PyObject * +permutations_setstate(permutationsobject *po, PyObject *state) +{ + PyObject *indices, *cycles, *result; + Py_ssize_t n, i; + + if (!PyArg_ParseTuple(state, "O!O!", + &PyTuple_Type, &indices, + &PyTuple_Type, &cycles)) + return NULL; + + n = PyTuple_GET_SIZE(po->pool); + if (PyTuple_GET_SIZE(indices) != n || + PyTuple_GET_SIZE(cycles) != po->r) + { + PyErr_SetString(PyExc_ValueError, "invalid arguments"); + return NULL; + } + + for (i=0; i n-1) + index = n-1; + po->indices[i] = index; + } + + 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()) + return NULL; /* not an integer */ + if (index < 1) + index = 1; + else if (index > n-i) + index = n-i; + po->cycles[i] = index; + } + result = PyTuple_New(po->r); + if (result == NULL) + return NULL; + for (i=0; ir; i++) { + PyObject *element = PyTuple_GET_ITEM(po->pool, po->indices[i]); + Py_INCREF(element); + PyTuple_SET_ITEM(result, i, element); + } + Py_CLEAR(po->result); + po->result = result; + Py_RETURN_NONE; +} + +static PyMethodDef permuations_methods[] = { + {"__reduce__", (PyCFunction)permutations_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)permutations_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(permutations_doc, "permutations(iterable[, r]) --> permutations object\n\ \n\ @@ -2574,7 +3254,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)permutations_next, /* tp_iternext */ - 0, /* tp_methods */ + permuations_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2605,7 +3285,7 @@ static char *kwargs[] = {"iterable", "func", NULL}; PyObject *iterable; PyObject *it; - PyObject *binop = NULL; + PyObject *binop = Py_None; accumulateobject *lz; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:accumulate", @@ -2624,8 +3304,10 @@ return NULL; } - Py_XINCREF(binop); - lz->binop = binop; + if (binop != Py_None) { + Py_XINCREF(binop); + lz->binop = binop; + } lz->total = NULL; lz->it = it; return (PyObject *)lz; @@ -2681,6 +3363,31 @@ return newtotal; } +static PyObject * +accumulate_reduce(accumulateobject *lz) +{ + 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) +{ + Py_CLEAR(lz->total); + lz->total = state; + Py_INCREF(lz->total); + Py_RETURN_NONE; +} + +static PyMethodDef accumulate_methods[] = { + {"__reduce__", (PyCFunction)accumulate_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)accumulate_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(accumulate_doc, "accumulate(iterable[, func]) --> accumulate object\n\ \n\ @@ -2716,7 +3423,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)accumulate_next, /* tp_iternext */ - 0, /* tp_methods */ + accumulate_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2833,6 +3540,19 @@ } } +static PyObject * +compress_reduce(compressobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), + lz->data, lz->selectors); + } + +static PyMethodDef compress_methods[] = { + {"__reduce__", (PyCFunction)compress_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(compress_doc, "compress(data, selectors) --> iterator over selected data\n\ \n\ @@ -2870,7 +3590,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)compress_next, /* tp_iternext */ - 0, /* tp_methods */ + compress_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2977,6 +3697,19 @@ } } +static PyObject * +filterfalse_reduce(filterfalseobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), + lz->func, lz->it); + } + +static PyMethodDef filterfalse_methods[] = { + {"__reduce__", (PyCFunction)filterfalse_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(filterfalse_doc, "filterfalse(function or None, sequence) --> filterfalse object\n\ \n\ @@ -3013,7 +3746,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)filterfalse_next, /* tp_iternext */ - 0, /* tp_methods */ + filterfalse_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -3207,11 +3940,9 @@ return Py_BuildValue("O(n)", Py_TYPE(lz), lz->cnt); } -PyDoc_STRVAR(count_reduce_doc, "Return state information for pickling."); - static PyMethodDef count_methods[] = { {"__reduce__", (PyCFunction)count_reduce, METH_NOARGS, - count_reduce_doc}, + reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -3352,8 +4083,21 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +repeat_reduce(repeatobject *ro) +{ + /* unpickle this so that a new repeat iterator is constructed with an + * object, then call __setstate__ on it to set cnt + */ + if (ro->cnt >= 0) + return Py_BuildValue("O(On)", Py_TYPE(ro), ro->element, ro->cnt); + else + return Py_BuildValue("O(O)", Py_TYPE(ro), ro->element); +} + static PyMethodDef repeat_methods[] = { {"__length_hint__", (PyCFunction)repeat_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)repeat_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -3579,6 +4323,49 @@ return result; } +static PyObject * +zip_longest_reduce(ziplongestobject *lz) +{ + + /* Create a new tuple with empty sequences where appropriate to pickle. + * Then use setstate to set the fillvalue + */ + int i; + PyObject *args = PyTuple_New(PyTuple_GET_SIZE(lz->ittuple)); + if (args == NULL) + return NULL; + for (i=0; iittuple); i++) { + PyObject *elem = PyTuple_GET_ITEM(lz->ittuple, i); + if (elem == NULL) { + elem = PyTuple_New(0); + if (elem == NULL) { + Py_DECREF(args); + return NULL; + } + } else + Py_INCREF(elem); + PyTuple_SET_ITEM(args, i, elem); + } + return Py_BuildValue("ONO", Py_TYPE(lz), args, lz->fillvalue); +} + +static PyObject * +zip_longest_setstate(ziplongestobject *lz, PyObject *state) +{ + Py_CLEAR(lz->fillvalue); + lz->fillvalue = state; + Py_INCREF(lz->fillvalue); + Py_RETURN_NONE; +} + +static PyMethodDef zip_longest_methods[] = { + {"__reduce__", (PyCFunction)zip_longest_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)zip_longest_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(zip_longest_doc, "zip_longest(iter1 [,iter2 [...]], [fillvalue=None]) --> zip_longest object\n\ \n\ @@ -3620,7 +4407,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)zip_longest_next, /* tp_iternext */ - 0, /* tp_methods */ + zip_longest_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -3708,6 +4495,9 @@ &product_type, &repeat_type, &groupby_type, + &_grouper_type, + &tee_type, + &teedataobject_type, NULL }; @@ -3725,11 +4515,5 @@ PyModule_AddObject(m, name+1, (PyObject *)typelist[i]); } - if (PyType_Ready(&teedataobject_type) < 0) - return NULL; - if (PyType_Ready(&tee_type) < 0) - return NULL; - if (PyType_Ready(&_grouper_type) < 0) - return NULL; return m; } diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -3003,7 +3003,7 @@ } static PyObject * -bytesarrayiter_length_hint(bytesiterobject *it) +bytearrayiter_length_hint(bytesiterobject *it) { Py_ssize_t len = 0; if (it->it_seq) @@ -3014,9 +3014,41 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +bytearrayiter_reduce(bytesiterobject *it) +{ + if (it->it_seq != NULL) { + return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + it->it_seq, it->it_index); + } else { + PyObject *u = PyUnicode_FromUnicode(NULL, 0); + if (u == NULL) + return NULL; + return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), u); + } +} + +static PyObject * +bytearrayiter_setstate(bytesiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->it_index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef bytearrayiter_methods[] = { - {"__length_hint__", (PyCFunction)bytesarrayiter_length_hint, METH_NOARGS, + {"__length_hint__", (PyCFunction)bytearrayiter_length_hint, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)bytearrayiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)bytearrayiter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3074,9 +3074,43 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +striter_reduce(striterobject *it) +{ + if (it->it_seq != NULL) { + return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + it->it_seq, it->it_index); + } else { + PyObject *u = PyUnicode_FromUnicode(NULL, 0); + if (u == NULL) + return NULL; + return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), u); + } +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +striter_setstate(striterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->it_index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef striter_methods[] = { {"__length_hint__", (PyCFunction)striter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)striter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)striter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2323,9 +2323,16 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +dictiter_reduce(dictiterobject *di); + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + static PyMethodDef dictiter_methods[] = { {"__length_hint__", (PyCFunction)dictiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)dictiter_reduce, METH_NOARGS, + reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -2560,6 +2567,52 @@ }; +static PyObject * +dictiter_reduce(dictiterobject *di) +{ + PyObject *list; + dictiterobject tmp; + + list = PyList_New(0); + if (!list) + return NULL; + + /* copy the itertor state */ + tmp = *di; + Py_XINCREF(tmp.di_dict); + + /* iterate the temporary into a list */ + for(;;) { + PyObject *element = 0; + if (Py_TYPE(di) == &PyDictIterItem_Type) + element = dictiter_iternextitem(&tmp); + else if (Py_TYPE(di) == &PyDictIterKey_Type) + element = dictiter_iternextkey(&tmp); + else if (Py_TYPE(di) == &PyDictIterValue_Type) + element = dictiter_iternextvalue(&tmp); + else + assert(0); + if (element) { + if (PyList_Append(list, element)) { + Py_DECREF(element); + Py_DECREF(list); + Py_XDECREF(tmp.di_dict); + return NULL; + } + Py_DECREF(element); + } else + break; + } + Py_XDECREF(tmp.di_dict); + /* check for error */ + if (tmp.di_dict != NULL) { + /* we have an error */ + Py_DECREF(list); + return NULL; + } + return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), list); +} + /***********************************************/ /* View objects for keys(), items(), values(). */ /***********************************************/ diff --git a/Objects/enumobject.c b/Objects/enumobject.c --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -158,6 +158,22 @@ return result; } +static PyObject * +enum_reduce(enumobject *en) +{ + if (en->en_longindex != NULL) + return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex); + else + return Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyMethodDef enum_methods[] = { + {"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(enum_doc, "enumerate(iterable[, start]) -> iterator for index, value of iterable\n" "\n" @@ -197,7 +213,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)enum_next, /* tp_iternext */ - 0, /* tp_methods */ + enum_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -319,8 +335,40 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +reversed_reduce(reversedobject *ro) +{ + if (ro->seq) + return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index); + else + return Py_BuildValue("O(())", Py_TYPE(ro)); +} + +static PyObject * +reversed_setstate(reversedobject *ro, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (ro->seq != 0) { + Py_ssize_t n = PySequence_Size(ro->seq); + if (n < 0) + return NULL; + if (index < -1) + index = -1; + else if (index > n-1) + index = n-1; + ro->index = index; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef reversediter_methods[] = { {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/iterobject.c b/Objects/iterobject.c --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -2,6 +2,19 @@ #include "Python.h" +/* Convenience function to get builtins.iter or builtins.reversed */ +PyObject * +_PyIter_GetBuiltin(const char *iter) +{ + PyObject *mod, *attr; + mod = PyImport_ImportModule("builtins"); + if (mod == NULL) + return NULL; + attr = PyObject_GetAttrString(mod, iter); + Py_DECREF(mod); + return attr; +} + typedef struct { PyObject_HEAD long it_index; @@ -88,8 +101,38 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +iter_reduce(seqiterobject *it) +{ + if (it->it_seq != NULL) + return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + it->it_seq, it->it_index); + else + return Py_BuildValue("N(())", _PyIter_GetBuiltin("iter")); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +iter_setstate(seqiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < 0) + index = 0; + it->it_index = index; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef seqiter_methods[] = { {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -195,6 +238,21 @@ return NULL; } +static PyObject * +calliter_reduce(calliterobject *it) +{ + if (it->it_callable != NULL && it->it_sentinel != NULL) + return Py_BuildValue("N(OO)", _PyIter_GetBuiltin("iter"), + it->it_callable, it->it_sentinel); + else + return Py_BuildValue("N(())", _PyIter_GetBuiltin("iter")); +} + +static PyMethodDef calliter_methods[] = { + {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyTypeObject PyCallIter_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "callable_iterator", /* tp_name */ @@ -224,7 +282,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)calliter_iternext, /* tp_iternext */ - 0, /* tp_methods */ + calliter_methods, /* tp_methods */ }; diff --git a/Objects/listobject.c b/Objects/listobject.c --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2660,11 +2660,18 @@ static int listiter_traverse(listiterobject *, visitproc, void *); static PyObject *listiter_next(listiterobject *); static PyObject *listiter_len(listiterobject *); +static PyObject *listiter_reduce_general(void *_it, int forward); +static PyObject *listiter_reduce(listiterobject *); +static PyObject *listiter_setstate(listiterobject *, PyObject *state); PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); static PyMethodDef listiter_methods[] = { {"__length_hint__", (PyCFunction)listiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)listiter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)listiter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -2771,6 +2778,27 @@ } return PyLong_FromLong(0); } + +static PyObject * +listiter_reduce(listiterobject *it) +{ + return listiter_reduce_general(it, 1); +} + +static PyObject * +listiter_setstate(listiterobject *it, PyObject *state) +{ + long index = PyLong_AsLong(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < 0) + index = 0; + it->it_index = index; + } + Py_RETURN_NONE; +} + /*********************** List Reverse Iterator **************************/ typedef struct { @@ -2784,9 +2812,13 @@ static int listreviter_traverse(listreviterobject *, visitproc, void *); static PyObject *listreviter_next(listreviterobject *); static PyObject *listreviter_len(listreviterobject *); +static PyObject *listreviter_reduce(listreviterobject *); +static PyObject *listreviter_setstate(listreviterobject *, PyObject *); static PyMethodDef listreviter_methods[] = { {"__length_hint__", (PyCFunction)listreviter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)listreviter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)listreviter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -2883,3 +2915,51 @@ len = 0; return PyLong_FromSsize_t(len); } + +static PyObject * +listreviter_reduce(listreviterobject *it) +{ + return listiter_reduce_general(it, 0); +} + +static PyObject * +listreviter_setstate(listreviterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < -1) + index = -1; + else if (index > PyList_GET_SIZE(it->it_seq) - 1) + index = PyList_GET_SIZE(it->it_seq) - 1; + it->it_index = index; + } + Py_RETURN_NONE; +} + +/* common pickling support */ + +static PyObject * +listiter_reduce_general(void *_it, int forward) +{ + PyObject *list; + + /* the objects are not the same, index is of different types! */ + if (forward) { + listiterobject *it = (listiterobject *)_it; + if (it->it_seq) + return Py_BuildValue("N(O)l", _PyIter_GetBuiltin("iter"), + it->it_seq, it->it_index); + } else { + listreviterobject *it = (listreviterobject *)_it; + if (it->it_seq) + return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("reversed"), + it->it_seq, it->it_index); + } + /* empty iterator, create an empty list */ + list = PyList_New(0); + if (list == NULL) + return NULL; + return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), list); +} diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -964,9 +964,59 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +rangeiter_reduce(rangeiterobject *r) +{ + PyObject *start=NULL, *stop=NULL, *step=NULL; + PyObject *range; + + /* create a range object for pickling */ + start = PyLong_FromLong(r->start); + if (start == NULL) + goto err; + stop = PyLong_FromLong(r->start + r->len * r->step); + if (stop == NULL) + goto err; + step = PyLong_FromLong(r->step); + if (step == NULL) + goto err; + range = (PyObject*)make_range_object(&PyRange_Type, + start, stop, step); + if (range == NULL) + goto err; + /* return the result */ + return Py_BuildValue("N(N)i", _PyIter_GetBuiltin("iter"), range, r->index); +err: + Py_XDECREF(start); + Py_XDECREF(stop); + Py_XDECREF(step); + return NULL; +} + +static PyObject * +rangeiter_setstate(rangeiterobject *r, PyObject *state) +{ + long index = PyLong_AsLong(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0 || index >= r->len) { + PyErr_SetString(PyExc_ValueError, "index out of range"); + return NULL; + } + r->index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef rangeiter_methods[] = { {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)rangeiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)rangeiter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -1095,9 +1145,51 @@ return PyNumber_Subtract(r->len, r->index); } +static PyObject * +longrangeiter_reduce(longrangeiterobject *r) +{ + PyObject *product, *stop=NULL; + PyObject *range; + + /* create a range object for pickling. Must calculate the "stop" value */ + product = PyNumber_Multiply(r->len, r->step); + if (product == NULL) + return NULL; + stop = PyNumber_Add(r->start, product); + Py_DECREF(product); + if (stop == NULL) + return NULL; + Py_INCREF(r->start); + Py_INCREF(r->step); + range = (PyObject*)make_range_object(&PyRange_Type, + r->start, stop, r->step); + if (range == NULL) { + Py_DECREF(r->start); + Py_DECREF(stop); + Py_DECREF(r->step); + return NULL; + } + + /* return the result */ + return Py_BuildValue("N(N)O", _PyIter_GetBuiltin("iter"), range, r->index); +} + +static PyObject * +longrangeiter_setstate(longrangeiterobject *r, PyObject *state) +{ + Py_CLEAR(r->index); + r->index = state; + Py_INCREF(r->index); + Py_RETURN_NONE; +} + static PyMethodDef longrangeiter_methods[] = { {"__length_hint__", (PyCFunction)longrangeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)longrangeiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)longrangeiter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -819,8 +819,51 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject *setiter_iternext(setiterobject *si); + +static PyObject * +setiter_reduce(setiterobject *si) +{ + PyObject *list; + setiterobject tmp; + + list = PyList_New(0); + if (!list) + return NULL; + + /* copy the itertor state */ + tmp = *si; + Py_XINCREF(tmp.si_set); + + /* iterate the temporary into a list */ + for(;;) { + PyObject *element = setiter_iternext(&tmp); + if (element) { + if (PyList_Append(list, element)) { + Py_DECREF(element); + Py_DECREF(list); + Py_XDECREF(tmp.si_set); + return NULL; + } + Py_DECREF(element); + } else + break; + } + Py_XDECREF(tmp.si_set); + /* check for error */ + if (tmp.si_set != NULL) { + /* we have an error */ + Py_DECREF(list); + return NULL; + } + return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), list); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + static PyMethodDef setiter_methods[] = { {"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)setiter_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -1964,8 +2007,6 @@ return result; } -PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); - static PyObject * set_sizeof(PySetObject *so) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -967,8 +967,39 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +tupleiter_reduce(tupleiterobject *it) +{ + if (it->it_seq) + return Py_BuildValue("N(O)l", _PyIter_GetBuiltin("iter"), + it->it_seq, it->it_index); + else + return Py_BuildValue("N(())", _PyIter_GetBuiltin("iter")); +} + +static PyObject * +tupleiter_setstate(tupleiterobject *it, PyObject *state) +{ + long index = PyLong_AsLong(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < 0) + index = 0; + else if (it->it_seq != NULL && index > PyTuple_GET_SIZE(it->it_seq)) + index = PyTuple_GET_SIZE(it->it_seq); + it->it_index = index; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef tupleiter_methods[] = { {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)tupleiter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)tupleiter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -14382,9 +14382,43 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +unicodeiter_reduce(unicodeiterobject *it) +{ + if (it->it_seq != NULL) { + return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + it->it_seq, it->it_index); + } else { + PyObject *u = PyUnicode_FromUnicode(NULL, 0); + if (u == NULL) + return NULL; + return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), u); + } +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +unicodeiter_setstate(unicodeiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->it_index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef unicodeiter_methods[] = { {"__length_hint__", (PyCFunction)unicodeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)unicodeiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)unicodeiter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -438,6 +438,19 @@ } } +static PyObject * +filter_reduce(filterobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->func, lz->it); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyMethodDef filter_methods[] = { + {"__reduce__", (PyCFunction)filter_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(filter_doc, "filter(function or None, iterable) --> filter object\n\ \n\ @@ -474,7 +487,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)filter_next, /* tp_iternext */ - 0, /* tp_methods */ + filter_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1054,6 +1067,31 @@ return result; } +static PyObject * +map_reduce(mapobject *lz) +{ + Py_ssize_t numargs = PyTuple_GET_SIZE(lz->iters); + PyObject *args = PyTuple_New(numargs+1); + Py_ssize_t i; + if (args == NULL) + return NULL; + Py_INCREF(lz->func); + PyTuple_SET_ITEM(args, 0, lz->func); + for (i = 0; iiters, i); + Py_INCREF(it); + PyTuple_SET_ITEM(args, i+1, it); + } + + return Py_BuildValue("ON", Py_TYPE(lz), args); +} + +static PyMethodDef map_methods[] = { + {"__reduce__", (PyCFunction)map_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + + PyDoc_STRVAR(map_doc, "map(func, *iterables) --> map object\n\ \n\ @@ -1090,7 +1128,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)map_next, /* tp_iternext */ - 0, /* tp_methods */ + map_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2238,6 +2276,18 @@ return result; } +static PyObject * +zip_reduce(zipobject *lz) +{ + /* Just recreate the zip with the internal iterator tuple */ + return Py_BuildValue("OO", Py_TYPE(lz), lz->ittuple); +} + +static PyMethodDef zip_methods[] = { + {"__reduce__", (PyCFunction)zip_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(zip_doc, "zip(iter1 [,iter2 [...]]) --> zip object\n\ \n\ @@ -2276,7 +2326,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)zip_next, /* tp_iternext */ - 0, /* tp_methods */ + zip_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 13:12:05 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 03 Apr 2012 13:12:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314288=3A_Modify_Mi?= =?utf8?q?sc/NEWS?= Message-ID: http://hg.python.org/cpython/rev/51c88d51aa4a changeset: 76092:51c88d51aa4a user: Kristj?n Valur J?nsson date: Tue Apr 03 10:59:26 2012 +0000 summary: Issue #14288: Modify Misc/NEWS 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 @@ -60,6 +60,8 @@ - Issue #14471: Fix a possible buffer overrun in the winreg module. +- Issue #14288: Allow the serialization of builtin iterators + Library ------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 14:00:18 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 03 Apr 2012 14:00:18 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Mention_CLOCK=5F*?= =?utf8?q?=5FCOARSE_and_Tools/pybench/systimes=2Epy?= Message-ID: http://hg.python.org/peps/rev/9a455a87ffac changeset: 4193:9a455a87ffac user: Victor Stinner date: Tue Apr 03 14:00:16 2012 +0200 summary: PEP 418: Mention CLOCK_*_COARSE and Tools/pybench/systimes.py files: pep-0418.txt | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -383,6 +383,12 @@ clock_gettime() requires to link the program against the rt (real-time) library. +.. note:: + + Linux provides also CLOCK_MONOTONIC_COARSE since Linux 2.6.32 which has less + accurate than CLOCK_MONOTONIC but is faster. + + Windows: QueryPerformanceCounter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -554,6 +560,11 @@ It looks like Linux does not implement clock_getres() and always return 1 nanosecond. +.. note:: + + Linux provides also CLOCK_REALTIME_COARSE since Linux 2.6.32 which has less + accurate than CLOCK_REALTIME but is faster. + Windows: GetSystemTimeAsFileTime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -621,6 +632,11 @@ always return 1 nanosecond. For GetProcessTimes(), the accuracy is read using GetSystemTimeAdjustment(). +Python source code includes a portable library to get the process time: +`Tools/pybench/systimes.py +`_. + + Functions ^^^^^^^^^ -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 3 14:47:31 2012 From: python-checkins at python.org (r.david.murray) Date: Tue, 03 Apr 2012 14:47:31 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0NDgxOiBmaXgg?= =?utf8?q?formatting_of_example_in_subprocess_docs=2E?= Message-ID: http://hg.python.org/cpython/rev/2c1ce04ded55 changeset: 76093:2c1ce04ded55 branch: 2.7 parent: 76083:013766e7a6eb user: R David Murray date: Tue Apr 03 08:46:05 2012 -0400 summary: #14481: fix formatting of example in subprocess docs. files: Doc/library/subprocess.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -685,7 +685,7 @@ to receive a SIGPIPE if p2 exits before p1. Alternatively, for trusted input, the shell's own pipeline support may still -be used directly: +be used directly:: output=`dmesg | grep hda` # becomes -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 14:47:33 2012 From: python-checkins at python.org (r.david.murray) Date: Tue, 03 Apr 2012 14:47:33 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NDgxOiBmaXgg?= =?utf8?q?formatting_of_example_in_subprocess_docs=2E?= Message-ID: http://hg.python.org/cpython/rev/e5f5652bfe91 changeset: 76094:e5f5652bfe91 branch: 3.2 parent: 76084:43606a4085b0 user: R David Murray date: Tue Apr 03 08:46:48 2012 -0400 summary: #14481: fix formatting of example in subprocess docs. files: Doc/library/subprocess.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -735,7 +735,7 @@ to receive a SIGPIPE if p2 exits before p1. Alternatively, for trusted input, the shell's own pipeline support may still -be used directly: +be used directly:: output=`dmesg | grep hda` # becomes -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 14:47:40 2012 From: python-checkins at python.org (r.david.murray) Date: Tue, 03 Apr 2012 14:47:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_=2314481=3A_fix_formatting_of_example_in_subprocess_do?= =?utf8?b?Y3Mu?= Message-ID: http://hg.python.org/cpython/rev/9599f091faa6 changeset: 76095:9599f091faa6 parent: 76092:51c88d51aa4a parent: 76094:e5f5652bfe91 user: R David Murray date: Tue Apr 03 08:47:14 2012 -0400 summary: Merge #14481: fix formatting of example in subprocess docs. files: Doc/library/subprocess.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -804,7 +804,7 @@ to receive a SIGPIPE if p2 exits before p1. Alternatively, for trusted input, the shell's own pipeline support may still -be used directly: +be used directly:: output=`dmesg | grep hda` # becomes -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 15:41:25 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 03 Apr 2012 15:41:25 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_Issue_=2314466=3A_remove_m?= =?utf8?q?q-based_workflow?= Message-ID: http://hg.python.org/devguide/rev/e1d4b6dc9702 changeset: 502:e1d4b6dc9702 user: Antoine Pitrou date: Tue Apr 03 15:36:14 2012 +0200 summary: Issue #14466: remove mq-based workflow files: patch.rst | 67 +++++++++++++----------------------------- 1 files changed, 21 insertions(+), 46 deletions(-) diff --git a/patch.rst b/patch.rst --- a/patch.rst +++ b/patch.rst @@ -10,57 +10,36 @@ Tool Usage '''''''''' -.. _mq-workflow: +.. _workflow: Mercurial allows for various workflows according to each person's or -project's preference. We present here a very simple solution based on mq_ -(*Mercurial Queues*). You are welcome to use any approach you like (including -a svn-like approach of simply using ``hg diff`` to create a patch based on -uncommitted changes in your working copy). Usage of mq_ is merely a -suggestion; it's a balance between being able to do everything needed -while allowing for more powerful usage if desired in the future. +project's preference. It is out of this guide's scope to present them all, +so we will stick to a basic workflow where you work on a patch in your +working copy without ever making any local commits. -First make sure that the extension has been turned on in your ``.hgrc`` or -``Mercurial.ini`` file:: +If you use this workflow, and your work adds or removes files to the +source tree, you will have to temporarily ``hg add`` or ``hg remove`` them, +respectively, before generating a patch. - [extensions] - mq = +To generate a patch, just invoke ``hg diff`` which will print out a +patch of the working copy's changes against the current revision:: -You can verify this is working properly by running ``hg help mq``. + hg diff > mywork.patch -Before you start modifying things in your working copy, type:: +If you want to undo your changes, you can revert them from the working copy:: - hg qnew mywork + hg revert -a -where ``mywork`` is a descriptive name for what you are going to work on. -This will create a patch in your patch queue. Whenever you have reached a point -that you want to save what you have done, run:: +You can later re-apply the changes if you want to continue working on the +patch:: - hg qrefresh + hg import --no-commit mywork.patch -This will update the patch to contain all of the changes you have made up to -this point. If you have added or removed any file, use ``hg add`` or ``hg -remove``, respectively, before running ``hg qrefresh``. - -Later on, we will explain :ref:`how to generate a patch `. - -If you want to delete your changes irrevocably (either because they were -committed, or they ended up uninteresting), use:: - - hg qpop mywork - hg qdelete mywork .. seealso:: - For more advanced usage of mq, read the `mq chapter - `_ - of `Mercurial: The Definitive Guide `_. - - Also, regardless of your workflow, refer to the :ref:`FAQ ` for + Refer to the :ref:`FAQ ` for :ref:`more information on using Mercurial `. -.. _issue tracker: http://bugs.python.org -.. _mq: http://mercurial.selenic.com/wiki/MqExtension - Preparation ''''''''''' @@ -123,19 +102,15 @@ ./python.exe Tools/scripts/patchcheck.py -Assuming you are using the :ref:`mq approach ` suggested earlier, -first check that all your local changes have been recorded (using -``hg qrefresh``), then type the following:: +Assuming you are using the :ref:`basic approach ` suggested earlier, +just type the following:: - hg qdiff > mywork.patch + hg diff > mywork.patch If you are using another approach, you probably need to find out the right invocation of ``hg diff`` for your purposes; see ``hg help diff`` and ``hg -help revisions``. Just please make sure that you -generate a **single, condensed** patch rather than a series of several changesets. - -Also, please make sure your patch is whitespace normalized. ``patchcheck`` -will check this for you. +help revisions``. Just please make sure that you generate a +**single, condensed** patch rather than a series of several changesets. Submitting -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Tue Apr 3 20:20:37 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 03 Apr 2012 20:20:37 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NDgy?= =?utf8?q?=3A_Raise_a_ValueError=2C_not_a_NameError=2C_when_trying_to_crea?= =?utf8?q?te?= Message-ID: http://hg.python.org/cpython/rev/57c0867fbf30 changeset: 76096:57c0867fbf30 branch: 3.2 parent: 76094:e5f5652bfe91 user: Antoine Pitrou date: Tue Apr 03 20:12:23 2012 +0200 summary: Issue #14482: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_UNIX type address under Windows. Patch by Popa Claudiu. files: Lib/multiprocessing/connection.py | 4 ++++ Lib/test/test_multiprocessing.py | 6 ++++++ Misc/NEWS | 4 ++++ 3 files changed, 14 insertions(+), 0 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -101,6 +101,10 @@ if sys.platform != 'win32' and family == 'AF_PIPE': raise ValueError('Family %s is not recognized.' % family) + if sys.platform == 'win32' and family == 'AF_UNIX': + # double check + if not hasattr(socket, family): + raise ValueError('Family %s is not recognized.' % family) def address_type(address): ''' diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2331,6 +2331,12 @@ with self.assertRaises(ValueError): multiprocessing.connection.Listener(r'\\.\test') + @unittest.skipUnless(WIN32, "skipped on non-Windows platforms") + def test_invalid_family_win32(self): + with self.assertRaises(ValueError): + multiprocessing.connection.Listener('/var/test.pipe') + + testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, TestStdinBadfiledescriptor, TestInvalidFamily] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,10 @@ Library ------- +- Issue #14482: Raise a ValueError, not a NameError, when trying to create + a multiprocessing Client or Listener with an AF_UNIX type address under + Windows. Patch by Popa Claudiu. + - Issue #14151: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 20:20:38 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 03 Apr 2012 20:20:38 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314482=3A_Raise_a_ValueError=2C_not_a_NameError=2C_w?= =?utf8?q?hen_trying_to_create?= Message-ID: http://hg.python.org/cpython/rev/ddc5adcedf29 changeset: 76097:ddc5adcedf29 parent: 76095:9599f091faa6 parent: 76096:57c0867fbf30 user: Antoine Pitrou date: Tue Apr 03 20:13:45 2012 +0200 summary: Issue #14482: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_UNIX type address under Windows. Patch by Popa Claudiu. files: Lib/multiprocessing/connection.py | 4 ++++ Lib/test/test_multiprocessing.py | 4 ++++ Misc/NEWS | 4 ++++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -111,6 +111,10 @@ if sys.platform != 'win32' and family == 'AF_PIPE': raise ValueError('Family %s is not recognized.' % family) + if sys.platform == 'win32' and family == 'AF_UNIX': + # double check + if not hasattr(socket, family): + raise ValueError('Family %s is not recognized.' % family) def address_type(address): ''' diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2649,6 +2649,10 @@ with self.assertRaises(ValueError): multiprocessing.connection.Listener(r'\\.\test') + @unittest.skipUnless(WIN32, "skipped on non-Windows platforms") + def test_invalid_family_win32(self): + with self.assertRaises(ValueError): + multiprocessing.connection.Listener('/var/test.pipe') testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, TestStdinBadfiledescriptor, TestWait, TestInvalidFamily] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #14482: Raise a ValueError, not a NameError, when trying to create + a multiprocessing Client or Listener with an AF_UNIX type address under + Windows. Patch by Popa Claudiu. + - Issue #802310: Generate always unique tkinter font names if not directly passed. - Issue #14151: Raise a ValueError, not a NameError, when trying to create -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 3 21:04:28 2012 From: python-checkins at python.org (eli.bendersky) Date: Tue, 03 Apr 2012 21:04:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fixes_and_enhancements_to_?= =?utf8?q?=5Felementtree=3A?= Message-ID: http://hg.python.org/cpython/rev/14abfa27ff19 changeset: 76098:14abfa27ff19 user: Eli Bendersky date: Tue Apr 03 22:02:37 2012 +0300 summary: Fixes and enhancements to _elementtree: * Fixed refleak problems when GC collection is run (see messages in issue #14065) * Added weakref support to Element objects files: Lib/test/test_xml_etree.py | 35 ++++++++++++ Modules/_elementtree.c | 71 +++++++++++++++++-------- 2 files changed, 82 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1859,6 +1859,41 @@ gc_collect() self.assertIsNone(wref()) + # A longer cycle: d->e->e2->d + e = ET.Element('joe') + d = Dummy() + d.dummyref = e + wref = weakref.ref(d) + e2 = ET.SubElement(e, 'foo', attr=d) + del d, e, e2 + gc_collect() + self.assertIsNone(wref()) + + # A cycle between Element objects as children of one another + # e1->e2->e3->e1 + e1 = ET.Element('e1') + e2 = ET.Element('e2') + e3 = ET.Element('e3') + e1.append(e2) + e2.append(e2) + e3.append(e1) + wref = weakref.ref(e1) + del e1, e2, e3 + gc_collect() + self.assertIsNone(wref()) + + def test_weakref(self): + flag = False + def wref_cb(w): + nonlocal flag + flag = True + e = ET.Element('e') + wref = weakref.ref(e, wref_cb) + self.assertEqual(wref().tag, 'e') + del e + self.assertEqual(flag, True) + self.assertEqual(wref(), None) + class ElementTreeTest(unittest.TestCase): def test_istype(self): diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -48,6 +48,7 @@ /* See http://www.python.org/psf/license for licensing details. */ #include "Python.h" +#include "structmember.h" #define VERSION "1.0.6" @@ -229,6 +230,8 @@ ElementObjectExtra* extra; + PyObject *weakreflist; /* For tp_weaklistoffset */ + } ElementObject; static PyTypeObject Element_Type; @@ -261,17 +264,24 @@ LOCAL(void) dealloc_extra(ElementObject* self) { + if (!self->extra) + return; + + /* Avoid DECREFs calling into this code again (cycles, etc.) + */ + ElementObjectExtra *myextra = self->extra; + self->extra = NULL; + + Py_DECREF(myextra->attrib); + int i; - - Py_DECREF(self->extra->attrib); - - for (i = 0; i < self->extra->length; i++) - Py_DECREF(self->extra->children[i]); - - if (self->extra->children != self->extra->_children) - PyObject_Free(self->extra->children); - - PyObject_Free(self->extra); + for (i = 0; i < myextra->length; i++) + Py_DECREF(myextra->children[i]); + + if (myextra->children != myextra->_children) + PyObject_Free(myextra->children); + + PyObject_Free(myextra); } /* Convenience internal function to create new Element objects with the given @@ -308,6 +318,8 @@ Py_INCREF(Py_None); self->tail = Py_None; + self->weakreflist = NULL; + ALLOC(sizeof(ElementObject), "create element"); PyObject_GC_Track(self); return (PyObject*) self; @@ -328,6 +340,7 @@ e->tail = Py_None; e->extra = NULL; + e->weakreflist = NULL; } return (PyObject *)e; } @@ -576,19 +589,28 @@ static int element_gc_clear(ElementObject *self) { - PyObject *text = JOIN_OBJ(self->text); - PyObject *tail = JOIN_OBJ(self->tail); Py_CLEAR(self->tag); - Py_CLEAR(text); - Py_CLEAR(tail); + + /* The following is like Py_CLEAR for self->text and self->tail, but + * written explicitily because the real pointers hide behind access + * macros. + */ + if (self->text) { + PyObject *tmp = JOIN_OBJ(self->text); + self->text = NULL; + Py_DECREF(tmp); + } + + if (self->tail) { + PyObject *tmp = JOIN_OBJ(self->tail); + self->tail = NULL; + Py_DECREF(tmp); + } /* After dropping all references from extra, it's no longer valid anyway, - ** so fully deallocate it (see also element_clearmethod) + * so fully deallocate it. */ - if (self->extra) { - dealloc_extra(self); - self->extra = NULL; - } + dealloc_extra(self); return 0; } @@ -596,6 +618,10 @@ element_dealloc(ElementObject* self) { PyObject_GC_UnTrack(self); + + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); + /* element_gc_clear clears all references and deallocates extra */ element_gc_clear(self); @@ -626,10 +652,7 @@ if (!PyArg_ParseTuple(args, ":clear")) return NULL; - if (self->extra) { - dealloc_extra(self); - self->extra = NULL; - } + dealloc_extra(self); Py_INCREF(Py_None); Py_DECREF(JOIN_OBJ(self->text)); @@ -1693,7 +1716,7 @@ (traverseproc)element_gc_traverse, /* tp_traverse */ (inquiry)element_gc_clear, /* tp_clear */ 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(ElementObject, weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ element_methods, /* tp_methods */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 4 01:00:53 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 04 Apr 2012 01:00:53 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_3_alternatives?= Message-ID: http://hg.python.org/peps/rev/763be41b879b changeset: 4194:763be41b879b user: Victor Stinner date: Wed Apr 04 01:00:46 2012 +0200 summary: PEP 418: Add 3 alternatives files: pep-0418.txt | 41 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 41 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -792,6 +792,47 @@ a monotonic clock with an unspecified starting point +Only expose operating system clocks +----------------------------------- + +To not have to define high-level clocks, which is a difficult task, a simpler +approach is to only expose operating system clocks. time.clock_gettime() and +related clock identifiers were already added to Python 3.3 for example. + + +Don't fallback on system clock +------------------------------ + +time.monotonic() is always a monotonic clock and is only available if the +operating system provides a monotonic clock. + +time.highres() is only available if the operating system provides a clock with +a high resolution (e.g. at least a microsecond or better). + + +One function choosing the clock from a list of constrains +--------------------------------------------------------- + +time.get_clock(*flags) with the following flags: + + * time.MONOTONIC: clock cannot go backard + * time.STEADY: clock rate is steady and the clock is not adjusted + * time.HIGHRES: clock with the highest resolutions + +time.get_clock() returns None if the clock is found and so calls can be chained +using the or operator. Example:: + + func = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time() + +Example of flags of system clocks: + + * QueryPerformanceCounter: MONOTONIC | HIGHRES + * GetTickCount: MONOTONIC | STEADY + * CLOCK_MONOTONIC: MONOTONIC | STEADY (or only MONOTONIC on Linux) + * CLOCK_MONOTONIC_RAW: MONOTONIC | STEADY + * gettimeofday(): (none) + + One function with a flag: time.monotonic(fallback=True) ------------------------------------------------------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 4 01:09:50 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 04 Apr 2012 01:09:50 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_definitions_of_?= =?utf8?q?=22monotonic=22_and_=22steady=22?= Message-ID: http://hg.python.org/peps/rev/dc0b671d6aa4 changeset: 4195:dc0b671d6aa4 user: Victor Stinner date: Wed Apr 04 01:07:55 2012 +0200 summary: PEP 418: Add definitions of "monotonic" and "steady" files: pep-0418.txt | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -219,6 +219,27 @@ daemon) +Definitions +=========== + +Monotonic +--------- + +A monotonic clock cannot go backward. It may give the same value for two close +reads depending on the clock resolution. + +On Linux, CLOCK_MONOTONIC is a monotonic clock but its rate is adjusted by NTP. + +Steady +------ + +A steady clock is a clock with a stable rate. + +The C++ Timeout Specifiction uses the following definition: "Objects of class +steady_clock represent clocks for which values of time_point advance at a +steady rate relative to real time. That is, the clock may not be adjusted." + + Hardware clocks =============== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 4 01:09:51 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 04 Apr 2012 01:09:51 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Rename_time=2Ehighr?= =?utf8?b?ZXMoKSB0byB0aW1lLnBlcmZfY291bnRlcigp?= Message-ID: http://hg.python.org/peps/rev/ebb521404664 changeset: 4196:ebb521404664 user: Victor Stinner date: Wed Apr 04 01:09:35 2012 +0200 summary: PEP 418: Rename time.highres() to time.perf_counter() files: pep-0418.txt | 32 +++++++++++++++++--------------- 1 files changed, 17 insertions(+), 15 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -13,7 +13,7 @@ Abstract ======== -Add time.steady(), time.highres(), time.get_clock_info(name) functions to +Add time.steady(), time.perf_counter(), time.get_clock_info(name) functions to Python 3.3. @@ -25,7 +25,7 @@ * Display the current time to a human (e.g. display a calendar or draw a wall clock): use system clock, i.e. time.time() or datetime.datetime.now(). -* Benchmark, profiling: time.highres(). +* Benchmark, profiling: time.perf_counter(). * Event scheduler, timeout: time.steady(). @@ -35,7 +35,7 @@ To fulfill the use cases, the functions' properties are: * time.time(): system clock, "wall clock". -* time.highres(): clock with the best accuracy. +* time.perf_counter(): clock with the best accuracy. * time.steady(): steady clock, should be monotonic * time.get_clock_info(name): get information on the specified time function @@ -165,8 +165,8 @@ different in two Python processes. -time.highres() --------------- +time.perf_counter() +------------------- Clock with the best available resolution. @@ -174,24 +174,24 @@ Pseudo-code:: - def highres(): - if highres.use_performance_counter: + def perf_counter(): + if perf_counter.use_performance_counter: try: return _time.QueryPerformanceCounter() except OSError: # QueryPerformanceFrequency() may fail, if the installed # hardware does not support a high-resolution performance # counter for example - highres.use_performance_counter = False - if highres.use_steady: + perf_counter.use_performance_counter = False + if perf_counter.use_steady: # Monotonic clock is preferred over system clock try: return time.steady() except OSError: - highres.use_steady = False + perf_counter.use_steady = False return time.time() - highres.use_performance_counter = (os.name == 'nt') - highres.use_steady = hasattr(time, 'steady') + perf_counter.use_performance_counter = (os.name == 'nt') + perf_counter.use_steady = hasattr(time, 'steady') time.get_clock_info(name) ------------------------- @@ -199,7 +199,7 @@ Get information on the specified clock. Supported clocks: * "clock": time.clock() - * "highres": time.highres() + * "perf_counter": time.perf_counter() * "steady": time.steady() * "time": time.time() @@ -794,8 +794,9 @@ Other names for new functions ----------------------------- -time.highres(): +time.perf_counter(): +* time.highres() * time.hires(): "hires" can be read as "to hire" as in "he hires a car to go on holiday", rather than a "HIgh-RESolution clock". * time.timer(): "it would be too easy to confuse with (or misspell as) @@ -827,8 +828,8 @@ time.monotonic() is always a monotonic clock and is only available if the operating system provides a monotonic clock. -time.highres() is only available if the operating system provides a clock with -a high resolution (e.g. at least a microsecond or better). +time.perf_counter() is only available if the operating system provides a clock +with a high resolution (e.g. at least a microsecond or better). One function choosing the clock from a list of constrains -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 4 01:50:04 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 04 Apr 2012 01:50:04 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_typo_=28Specifi?= =?utf8?q?ction=29?= Message-ID: http://hg.python.org/peps/rev/060641887edf changeset: 4197:060641887edf user: Victor Stinner date: Wed Apr 04 01:49:55 2012 +0200 summary: PEP 418: Fix typo (Specifiction) files: pep-0418.txt | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -235,9 +235,11 @@ A steady clock is a clock with a stable rate. -The C++ Timeout Specifiction uses the following definition: "Objects of class -steady_clock represent clocks for which values of time_point advance at a -steady rate relative to real time. That is, the clock may not be adjusted." +The `C++ Timeout Specification +`_ uses the +following definition: "Objects of class steady_clock represent clocks for which +values of time_point advance at a steady rate relative to real time. That is, +the clock may not be adjusted." Hardware clocks @@ -835,7 +837,7 @@ One function choosing the clock from a list of constrains --------------------------------------------------------- -time.get_clock(*flags) with the following flags: +``time.get_clock(*flags)`` with the following flags: * time.MONOTONIC: clock cannot go backard * time.STEADY: clock rate is steady and the clock is not adjusted -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 4 01:57:47 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 04 Apr 2012 01:57:47 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_issues_of_the_h?= =?utf8?q?acked_monotonic_function?= Message-ID: http://hg.python.org/peps/rev/c568a59a3b83 changeset: 4198:c568a59a3b83 user: Victor Stinner date: Wed Apr 04 01:57:37 2012 +0200 summary: PEP 418: Add issues of the hacked monotonic function files: pep-0418.txt | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -900,6 +900,13 @@ `KB274323`_ contains a code example to workaround the bug (use GetTickCount() to detect QueryPerformanceCounter() leap). +Issues of a hacked monotonic function: + + * if the clock is accidentally set forward by an hour and then back + again, you wouldn't have a useful clock for an hour + * the cache is not shared between processes so different processes wouldn't + see the same clock value + Footnotes ========= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 4 02:58:04 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 04 Apr 2012 02:58:04 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Rewrite_the_PEP_418?= Message-ID: http://hg.python.org/peps/rev/5f1708dfd267 changeset: 4199:5f1708dfd267 user: Victor Stinner date: Wed Apr 04 02:57:55 2012 +0200 summary: Rewrite the PEP 418 * Rename time.steady() to time.monotonic(), again * time.monotonic() does not fallback to the system clock anymore * Drop time.perf_counter() function files: pep-0418.txt | 209 ++++++++++++++++---------------------- 1 files changed, 86 insertions(+), 123 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1,5 +1,5 @@ PEP: 418 -Title: Add steady and high-resolution time functions +Title: Add a monotonic time functions Version: $Revision$ Last-Modified: $Date$ Author: Victor Stinner @@ -13,8 +13,7 @@ Abstract ======== -Add time.steady(), time.perf_counter(), time.get_clock_info(name) functions to -Python 3.3. +Add time.monotonic() and time.get_clock_info(name) functions to Python 3.3. Rationale @@ -25,8 +24,9 @@ * Display the current time to a human (e.g. display a calendar or draw a wall clock): use system clock, i.e. time.time() or datetime.datetime.now(). -* Benchmark, profiling: time.perf_counter(). -* Event scheduler, timeout: time.steady(). +* Event scheduler, timeout: time.monotonic(). +* Benchmark, profiling: time.clock() on Windows, time.monotonic(), + or fallback to time.time() Functions @@ -35,8 +35,7 @@ To fulfill the use cases, the functions' properties are: * time.time(): system clock, "wall clock". -* time.perf_counter(): clock with the best accuracy. -* time.steady(): steady clock, should be monotonic +* time.monotonic(): monotonic clock * time.get_clock_info(name): get information on the specified time function @@ -78,129 +77,75 @@ return _time.time() -time.steady() -------------- +time.monotonic() +---------------- -Steady clock. Use a monotonic clock, or falls back to the system clock. Its -rate may be adjusted by NTP. The reference point of the returned value is -undefined so only the difference of consecutive calls is valid. - -Use time.get_clock_info('steady')['is_monotonic'] to check if the clock -monotonic or not. +Monotonic clock, cannot go backward. Its rate may be adjusted by NTP. The +reference point of the returned value is undefined so only the difference of +consecutive calls is valid. The elapsed time may or may not include time the system spends in sleep or hibernation; this depends on the operating system. +Availability: Windows, Mac OS X, Unix. + Pseudo-code [#pseudo]_:: if os.name == 'nt': # GetTickCount64() requires Windows Vista, Server 2008 or later if hasattr(time, '_GetTickCount64'): - def steady(): + def monotonic(): return _time.GetTickCount64() * 1e-3 else: - def steady(): + def monotonic(): ticks = _time.GetTickCount() - if ticks < steady.last: + if ticks < monotonic.last: # Integer overflow detected - steady.delta += 2**32 - steady.last = ticks - return (ticks + steady.delta) * 1e-3 - steady.last = 0 - steady.delta = 0 + monotonic.delta += 2**32 + monotonic.last = ticks + return (ticks + monotonic.delta) * 1e-3 + monotonic.last = 0 + monotonic.delta = 0 elif os.name == 'mac': - def steady(): - if steady.factor is None: + def monotonic(): + if monotonic.factor is None: factor = _time.mach_timebase_info() - steady.factor = timebase[0] / timebase[1] - return _time.mach_absolute_time() * steady.factor - steady.factor = None + monotonic.factor = timebase[0] / timebase[1] + return _time.mach_absolute_time() * monotonic.factor + monotonic.factor = None - elif os.name.startswith('sunos'): - def steady(): - if steady.use_clock_highres: + elif hasattr(time, "clock_gettime"): + def monotonic(): + if monotonic.use_clock_highres: try: time.clock_gettime(time.CLOCK_HIGHRES) except OSError: - steady.use_clock_highres = False - if steady.use_gethrtime: - try: - return time.gethrtime() - except OSError: - steady.use_gethrtime = False - return time.time() - steady.use_clock_highres = (hasattr(time, 'clock_gettime') + monotonic.use_clock_highres = False + return time.clock_gettime(time.CLOCK_MONOTONIC) + monotonic.use_clock_highres = (hasattr(time, 'clock_gettime') and hasattr(time, 'CLOCK_HIGHRES')) - steady.use_gethrtime = True - elif hasattr(time, "clock_gettime"): - def steady(): - while steady.clocks: - try: - clk_id = steady.clocks[0] - return time.clock_gettime(clk_id) - except OSError: - del steady.clocks[0] - return time.time() - steady.clocks = [] - if hasattr(time, 'CLOCK_HIGHRES'): - steady.clocks.append(time.CLOCK_HIGHRES) - steady.clocks.append(time.CLOCK_MONOTONIC) - else: - def steady(): - return time.time() - -On Windows, QueryPerformanceCounter() is not used even though it has a -better resolution than GetTickCount(). It is not reliable and has too -many issues. +On Windows, QueryPerformanceCounter() is not used even though it has a better +accuracy than GetTickCount(). It is not reliable and has too many issues. .. note:: - time.steady() detects GetTickCount() integer overflow (32 bits, - roll-over after 49.7 days): it increases a delta by 2\ :sup:`32` - each time than an overflow is detected. The delta is stored in the - process-local state and so the value of time.steady() may be - different in two Python processes. + time.monotonic() detects GetTickCount() integer overflow (32 bits, roll-over + after 49.7 days): it increases a delta by 2\ :sup:`32` each time than an + overflow is detected. The delta is stored in the process-local state and so + the value of time.monotonic() may be different in two Python processes + running for more than 49 days. -time.perf_counter() -------------------- - -Clock with the best available resolution. - -It is available on all platforms and cannot fail. - -Pseudo-code:: - - def perf_counter(): - if perf_counter.use_performance_counter: - try: - return _time.QueryPerformanceCounter() - except OSError: - # QueryPerformanceFrequency() may fail, if the installed - # hardware does not support a high-resolution performance - # counter for example - perf_counter.use_performance_counter = False - if perf_counter.use_steady: - # Monotonic clock is preferred over system clock - try: - return time.steady() - except OSError: - perf_counter.use_steady = False - return time.time() - perf_counter.use_performance_counter = (os.name == 'nt') - perf_counter.use_steady = hasattr(time, 'steady') - time.get_clock_info(name) ------------------------- Get information on the specified clock. Supported clocks: * "clock": time.clock() - * "perf_counter": time.perf_counter() - * "steady": time.steady() + * "monotonic": time.monotonic() * "time": time.time() Return a dictionary with the following keys: @@ -264,8 +209,8 @@ 32,768 Hz -NTP adjusted -============ +NTP adjustment +============== NTP has diffent methods to adjust a clock: @@ -655,10 +600,6 @@ always return 1 nanosecond. For GetProcessTimes(), the accuracy is read using GetSystemTimeAdjustment(). -Python source code includes a portable library to get the process time: -`Tools/pybench/systimes.py -`_. - Functions ^^^^^^^^^ @@ -793,27 +734,17 @@ Alternatives: API design ======================== -Other names for new functions ------------------------------ +Other names for time.monotonic() +-------------------------------- -time.perf_counter(): - -* time.highres() -* time.hires(): "hires" can be read as "to hire" as in "he hires a car - to go on holiday", rather than a "HIgh-RESolution clock". -* time.timer(): "it would be too easy to confuse with (or misspell as) - time.time()" - -time.steady(): - -* time.monotonic(): QueryPerformanceCounter() is monotonic but it is not used - by time.steady() because it is not steady, and it is surprising to have to - check for time.get_clock_info('monotonic')['is_monotonic']. -* time.try_monotonic(): it is a clear and obvious solution for the - use-case of "I prefer the monotonic clock, if it is available, - otherwise I'll take my chances with a best-effect clock." +* time.steady() * time.wallclock(): it is not the system time aka the "wall clock", but a monotonic clock with an unspecified starting point +* time.seconds() +* time.counter() + +The name "time.try_monotonic()" was also proposed when time.monotonic() was +falling back to the system clock when no monotonic clock was available. Only expose operating system clocks @@ -824,14 +755,18 @@ related clock identifiers were already added to Python 3.3 for example. -Don't fallback on system clock ------------------------------- +Fallback to system clock +------------------------ -time.monotonic() is always a monotonic clock and is only available if the -operating system provides a monotonic clock. +If no monotonic clock is available, time.monotonic() falls back to the system +clock. -time.perf_counter() is only available if the operating system provides a clock -with a high resolution (e.g. at least a microsecond or better). +Issues: + + * It is hard to define correctly such function in the documentation: is it + monotonic? is it steady? is it adjusted? + * Some user want to decide what to do when no monotonic clock is available: + use another clock, display an error, or do something else One function choosing the clock from a list of constrains @@ -846,7 +781,8 @@ time.get_clock() returns None if the clock is found and so calls can be chained using the or operator. Example:: - func = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time() + get_time = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time() + t = get_time() Example of flags of system clocks: @@ -854,7 +790,7 @@ * GetTickCount: MONOTONIC | STEADY * CLOCK_MONOTONIC: MONOTONIC | STEADY (or only MONOTONIC on Linux) * CLOCK_MONOTONIC_RAW: MONOTONIC | STEADY - * gettimeofday(): (none) + * gettimeofday(): (no flag) One function with a flag: time.monotonic(fallback=True) @@ -908,6 +844,29 @@ see the same clock value +Deferred API: time.perf_counter() +================================= + +Python does not provide a portable "performance counter" clock for benchmarking +or profiling. Each tool has to implement its own heuristic to decide which +clock is the best depending on the OS and on which counters are available. + +A previous version of the PEP proposed a time.perf_counter() function using +QueryPerformanceCounter() on Windows, time.monotonic(), or falls back to the +system time. This function was not well defined and the idea is deferred. + +Proposed names for such function: + + * time.hires() + * time.highres() + * time.perf_counter() + * time.timer() + +Python source code includes a portable library to get the process time: +`Tools/pybench/systimes.py +`_. + + Footnotes ========= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 4 03:48:02 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 04 Apr 2012 03:48:02 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_also_timeout=5F?= =?utf8?q?clock=28=29_alternative_name?= Message-ID: http://hg.python.org/peps/rev/d1bbe228a3af changeset: 4200:d1bbe228a3af user: Victor Stinner date: Wed Apr 04 03:47:55 2012 +0200 summary: PEP 418: Add also timeout_clock() alternative name files: pep-0418.txt | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -737,11 +737,12 @@ Other names for time.monotonic() -------------------------------- +* time.counter() +* time.seconds() * time.steady() +* time.timeout_clock() * time.wallclock(): it is not the system time aka the "wall clock", but a monotonic clock with an unspecified starting point -* time.seconds() -* time.counter() The name "time.try_monotonic()" was also proposed when time.monotonic() was falling back to the system clock when no monotonic clock was available. -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Wed Apr 4 05:34:37 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 04 Apr 2012 05:34:37 +0200 Subject: [Python-checkins] Daily reference leaks (14abfa27ff19): sum=0 Message-ID: results for 14abfa27ff19 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogehBBEr', '-x'] From python-checkins at python.org Wed Apr 4 13:21:01 2012 From: python-checkins at python.org (matthias.klose) Date: Wed, 04 Apr 2012 13:21:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Followup_for_issue_=2314321?= =?utf8?q?=2C_remove_references_to_Parser/pgen=2Estamp?= Message-ID: http://hg.python.org/cpython/rev/4e306c1a3c92 changeset: 76099:4e306c1a3c92 user: Matthias Klose date: Wed Apr 04 13:20:55 2012 +0200 summary: Followup for issue #14321, remove references to Parser/pgen.stamp files: .bzrignore | 1 - .gitignore | 1 - .hgignore | 1 - Makefile.pre.in | 2 +- 4 files changed, 1 insertions(+), 4 deletions(-) diff --git a/.bzrignore b/.bzrignore --- a/.bzrignore +++ b/.bzrignore @@ -33,7 +33,6 @@ Modules/config.c Modules/ld_so_aix Parser/pgen -Parser/pgen.stamp Lib/test/data/* Lib/lib2to3/Grammar*.pickle Lib/lib2to3/PatternGrammar*.pickle diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ PCbuild/*.pdb PCbuild/Win32-temp-* Parser/pgen -Parser/pgen.stamp __pycache__ autom4te.cache build/ diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -32,7 +32,6 @@ Modules/config.c Modules/ld_so_aix$ Parser/pgen$ -Parser/pgen.stamp$ PCbuild/amd64/ ^core ^python-gdb.py diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1351,7 +1351,7 @@ clobber: clean profile-removal -rm -f $(BUILDPYTHON) $(PGEN) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \ - tags TAGS Parser/pgen.stamp \ + tags TAGS \ config.cache config.log pyconfig.h Modules/config.c -rm -rf build platform -rm -rf $(PYTHONFRAMEWORKDIR) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 4 13:26:54 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 04 Apr 2012 13:26:54 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_Boost=2EChrono_?= =?utf8?q?library_in_links?= Message-ID: http://hg.python.org/peps/rev/8dc2457f0c5c changeset: 4201:8dc2457f0c5c user: Victor Stinner date: Wed Apr 04 13:26:35 2012 +0200 summary: PEP 418: Add Boost.Chrono library in links files: pep-0418.txt | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -916,6 +916,24 @@ * `libpthread `_: POSIX thread library for Windows (`clock.c `_) +* `Boost.Chrono + `_ uses: + + * system_clock: + + * mac = gettimeofday() + * posix = clock_gettime(CLOCK_REALTIME) + * win = GetSystemTimeAsFileTime() + + * steady_clock: + + * mac = mach_absolute_time() + * posix = clock_gettime(CLOCK_MONOTONIC) + * win = QueryPerformanceCounter() + + * high_resolution_clock: + + * steady_clock, if available system_clock, otherwise Time: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 4 14:19:10 2012 From: python-checkins at python.org (matthias.klose) Date: Wed, 04 Apr 2012 14:19:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_-_Issue_=2314493=3A_Use_gvf?= =?utf8?q?s-open/xdg-open_in_Lib/webbrowser=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/70c58903b52e changeset: 76100:70c58903b52e user: Matthias Klose date: Wed Apr 04 14:19:04 2012 +0200 summary: - Issue #14493: Use gvfs-open/xdg-open in Lib/webbrowser.py. files: Lib/webbrowser.py | 8 ++++++++ Misc/NEWS | 2 ++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -448,6 +448,14 @@ def register_X_browsers(): + # use xdg-open if around + if _iscommand("xdg-open"): + register("xdg-open", None, BackgroundBrowser("xdg-open")) + + # The default GNOME3 browser + if "GNOME_DESKTOP_SESSION_ID" in os.environ and _iscommand("gvfs-open"): + register("gvfs-open", None, BackgroundBrowser("gvfs-open")) + # The default GNOME browser if "GNOME_DESKTOP_SESSION_ID" in os.environ and _iscommand("gnome-open"): register("gnome-open", None, BackgroundBrowser("gnome-open")) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,8 @@ a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. +- Issue #14493: Use gvfs-open/xdg-open in Lib/webbrowser.py. + What's New in Python 3.3.0 Alpha 2? =================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 4 14:57:06 2012 From: python-checkins at python.org (eli.bendersky) Date: Wed, 04 Apr 2012 14:57:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_Windows_compilation_err?= =?utf8?q?ors?= Message-ID: http://hg.python.org/cpython/rev/118729090dc5 changeset: 76101:118729090dc5 user: Eli Bendersky date: Wed Apr 04 15:55:07 2012 +0300 summary: Fix Windows compilation errors files: Modules/_elementtree.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -264,17 +264,19 @@ LOCAL(void) dealloc_extra(ElementObject* self) { + ElementObjectExtra *myextra; + int i; + if (!self->extra) return; /* Avoid DECREFs calling into this code again (cycles, etc.) */ - ElementObjectExtra *myextra = self->extra; + myextra = self->extra; self->extra = NULL; Py_DECREF(myextra->attrib); - int i; for (i = 0; i < myextra->length; i++) Py_DECREF(myextra->children[i]); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 4 20:17:22 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 04 Apr 2012 20:17:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Closes_=2314495?= =?utf8?q?=3A_fix_typo=2E?= Message-ID: http://hg.python.org/cpython/rev/45287f2799f5 changeset: 76102:45287f2799f5 branch: 3.2 parent: 76096:57c0867fbf30 user: Georg Brandl date: Wed Apr 04 20:17:06 2012 +0200 summary: Closes #14495: fix typo. files: Lib/tkinter/ttk.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -1253,7 +1253,7 @@ def exists(self, item): - """Returns True if the specified item is present in the three, + """Returns True if the specified item is present in the tree, False otherwise.""" return bool(self.tk.call(self._w, "exists", item)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 4 20:17:23 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 04 Apr 2012 20:17:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/68ef2fc47da6 changeset: 76103:68ef2fc47da6 parent: 76101:118729090dc5 parent: 76102:45287f2799f5 user: Georg Brandl date: Wed Apr 04 20:17:27 2012 +0200 summary: merge with 3.2 files: Lib/tkinter/ttk.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -1253,7 +1253,7 @@ def exists(self, item): - """Returns True if the specified item is present in the three, + """Returns True if the specified item is present in the tree, False otherwise.""" return bool(self.tk.call(self._w, "exists", item)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 4 20:19:16 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 04 Apr 2012 20:19:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Transplant_4528?= =?utf8?q?7f2799f5_from_default_branch=2E?= Message-ID: http://hg.python.org/cpython/rev/9b472b24e5c9 changeset: 76104:9b472b24e5c9 branch: 2.7 parent: 76093:2c1ce04ded55 user: Georg Brandl date: Wed Apr 04 20:19:09 2012 +0200 summary: Transplant 45287f2799f5 from default branch. files: Lib/lib-tk/ttk.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/lib-tk/ttk.py b/Lib/lib-tk/ttk.py --- a/Lib/lib-tk/ttk.py +++ b/Lib/lib-tk/ttk.py @@ -1253,7 +1253,7 @@ def exists(self, item): - """Returns True if the specified item is present in the three, + """Returns True if the specified item is present in the tree, False otherwise.""" return bool(self.tk.call(self._w, "exists", item)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 00:11:58 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 05 Apr 2012 00:11:58 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Rename_=5FPyIter=5FGetBuilt?= =?utf8?q?in_to_=5FPyObject=5FGetBuiltin=2C_and_do_not_include_it_in_the?= Message-ID: http://hg.python.org/cpython/rev/fb907ee4fdfa changeset: 76105:fb907ee4fdfa parent: 76103:68ef2fc47da6 user: Antoine Pitrou date: Thu Apr 05 00:04:20 2012 +0200 summary: Rename _PyIter_GetBuiltin to _PyObject_GetBuiltin, and do not include it in the stable ABI. files: Include/iterobject.h | 2 -- Include/object.h | 5 +++++ Modules/arraymodule.c | 2 +- Objects/bytearrayobject.c | 4 ++-- Objects/bytesobject.c | 4 ++-- Objects/dictobject.c | 2 +- Objects/iterobject.c | 21 ++++----------------- Objects/listobject.c | 6 +++--- Objects/object.c | 13 +++++++++++++ Objects/rangeobject.c | 4 ++-- Objects/setobject.c | 2 +- Objects/tupleobject.c | 4 ++-- Objects/unicodeobject.c | 4 ++-- 13 files changed, 38 insertions(+), 35 deletions(-) diff --git a/Include/iterobject.h b/Include/iterobject.h --- a/Include/iterobject.h +++ b/Include/iterobject.h @@ -18,8 +18,6 @@ PyAPI_FUNC(PyObject *) PyCallIter_New(PyObject *, PyObject *); -PyAPI_FUNC(PyObject *) _PyIter_GetBuiltin(const char *iter); - #ifdef __cplusplus } #endif diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -535,6 +535,11 @@ _PyObject_GenericSetAttrWithDict(PyObject *, PyObject *, PyObject *, PyObject *); +/* Helper to look up a builtin object */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) +_PyObject_GetBuiltin(const char *name); +#endif /* PyObject_Dir(obj) acts like Python builtins.dir(obj), returning a list of strings. PyObject_Dir(NULL) is like builtins.dir(), diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2756,7 +2756,7 @@ static PyObject * arrayiter_reduce(arrayiterobject *it) { - return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), it->ao, it->index); } diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -3018,13 +3018,13 @@ bytearrayiter_reduce(bytesiterobject *it) { if (it->it_seq != NULL) { - return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), it->it_seq, it->it_index); } else { PyObject *u = PyUnicode_FromUnicode(NULL, 0); if (u == NULL) return NULL; - return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), u); + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), u); } } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3078,13 +3078,13 @@ striter_reduce(striterobject *it) { if (it->it_seq != NULL) { - return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), it->it_seq, it->it_index); } else { PyObject *u = PyUnicode_FromUnicode(NULL, 0); if (u == NULL) return NULL; - return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), u); + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), u); } } diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2610,7 +2610,7 @@ Py_DECREF(list); return NULL; } - return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), list); + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); } /***********************************************/ diff --git a/Objects/iterobject.c b/Objects/iterobject.c --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -2,19 +2,6 @@ #include "Python.h" -/* Convenience function to get builtins.iter or builtins.reversed */ -PyObject * -_PyIter_GetBuiltin(const char *iter) -{ - PyObject *mod, *attr; - mod = PyImport_ImportModule("builtins"); - if (mod == NULL) - return NULL; - attr = PyObject_GetAttrString(mod, iter); - Py_DECREF(mod); - return attr; -} - typedef struct { PyObject_HEAD long it_index; @@ -105,10 +92,10 @@ iter_reduce(seqiterobject *it) { if (it->it_seq != NULL) - return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), it->it_seq, it->it_index); else - return Py_BuildValue("N(())", _PyIter_GetBuiltin("iter")); + return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter")); } PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); @@ -242,10 +229,10 @@ calliter_reduce(calliterobject *it) { if (it->it_callable != NULL && it->it_sentinel != NULL) - return Py_BuildValue("N(OO)", _PyIter_GetBuiltin("iter"), + return Py_BuildValue("N(OO)", _PyObject_GetBuiltin("iter"), it->it_callable, it->it_sentinel); else - return Py_BuildValue("N(())", _PyIter_GetBuiltin("iter")); + return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter")); } static PyMethodDef calliter_methods[] = { diff --git a/Objects/listobject.c b/Objects/listobject.c --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2949,17 +2949,17 @@ if (forward) { listiterobject *it = (listiterobject *)_it; if (it->it_seq) - return Py_BuildValue("N(O)l", _PyIter_GetBuiltin("iter"), + return Py_BuildValue("N(O)l", _PyObject_GetBuiltin("iter"), it->it_seq, it->it_index); } else { listreviterobject *it = (listreviterobject *)_it; if (it->it_seq) - return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("reversed"), + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("reversed"), it->it_seq, it->it_index); } /* empty iterator, create an empty list */ list = PyList_New(0); if (list == NULL) return NULL; - return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), list); + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); } diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1026,6 +1026,19 @@ return obj; } +/* Convenience function to get a builtin from its name */ +PyObject * +_PyObject_GetBuiltin(const char *name) +{ + PyObject *mod, *attr; + mod = PyImport_ImportModule("builtins"); + if (mod == NULL) + return NULL; + attr = PyObject_GetAttrString(mod, name); + Py_DECREF(mod); + return attr; +} + /* Helper used when the __next__ method is removed from a type: tp_iternext is never NULL and can be safely called without checking on every iteration. diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -985,7 +985,7 @@ if (range == NULL) goto err; /* return the result */ - return Py_BuildValue("N(N)i", _PyIter_GetBuiltin("iter"), range, r->index); + return Py_BuildValue("N(N)i", _PyObject_GetBuiltin("iter"), range, r->index); err: Py_XDECREF(start); Py_XDECREF(stop); @@ -1171,7 +1171,7 @@ } /* return the result */ - return Py_BuildValue("N(N)O", _PyIter_GetBuiltin("iter"), range, r->index); + return Py_BuildValue("N(N)O", _PyObject_GetBuiltin("iter"), range, r->index); } static PyObject * diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -856,7 +856,7 @@ Py_DECREF(list); return NULL; } - return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), list); + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); } PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -971,10 +971,10 @@ tupleiter_reduce(tupleiterobject *it) { if (it->it_seq) - return Py_BuildValue("N(O)l", _PyIter_GetBuiltin("iter"), + return Py_BuildValue("N(O)l", _PyObject_GetBuiltin("iter"), it->it_seq, it->it_index); else - return Py_BuildValue("N(())", _PyIter_GetBuiltin("iter")); + return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter")); } static PyObject * diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -14386,13 +14386,13 @@ unicodeiter_reduce(unicodeiterobject *it) { if (it->it_seq != NULL) { - return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"), + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), it->it_seq, it->it_index); } else { PyObject *u = PyUnicode_FromUnicode(NULL, 0); if (u == NULL) return NULL; - return Py_BuildValue("N(N)", _PyIter_GetBuiltin("iter"), u); + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), u); } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 00:42:56 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 05 Apr 2012 00:42:56 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_link_to_Monoclo?= =?utf8?q?ck_library_and_an_old_article_on_Windows_clocks?= Message-ID: http://hg.python.org/peps/rev/d0033fc0844f changeset: 4202:d0033fc0844f user: Victor Stinner date: Thu Apr 05 00:38:51 2012 +0200 summary: PEP 418: Add link to Monoclock library and an old article on Windows clocks Mention also another issue of QueryPerformanceCounter() files: pep-0418.txt | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -411,6 +411,9 @@ each processor. The bug was fixed in Windows XP SP2. * Issues with processor with variable frequency: the frequency is changed depending on the workload to reduce memory consumption. +* Chromium don't use QueryPerformanceCounter() on Athlon X2 CPUs (model 15) + because "QueryPerformanceCounter is unreliable" (see base/time_win.cc in + Chromium source code) .. _KB896256: http://support.microsoft.com/?id=896256 .. _KB274323: http://support.microsoft.com/?id=274323 @@ -905,6 +908,9 @@ * `python-monotonic-time `_ (`github `_) +* `Monoclock.nano_count() + `_ uses clock_gettime(CLOCK_MONOTONIC) + and returns a number of nanoseconds * `monotonic_clock `_ * `Perl: Time::HiRes `_ exposes clock_gettime(CLOCK_MONOTONIC) @@ -961,6 +967,8 @@ `_: How the IBM High Resolution Time Stamp Facility accurately measures itty bits of time +* `Win32 Performance Measurement Options + `_ by Matthew Wilson, May 01, 2003 Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 5 03:29:46 2012 From: python-checkins at python.org (r.david.murray) Date: Thu, 05 Apr 2012 03:29:46 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NDkwLCAjMTQ0?= =?utf8?q?91=3A_add_=27sundry=27-style_import_tests_for_Tools/scripts=2E?= Message-ID: http://hg.python.org/cpython/rev/62dde5dd475e changeset: 76106:62dde5dd475e branch: 3.2 parent: 76102:45287f2799f5 user: R David Murray date: Wed Apr 04 21:28:14 2012 -0400 summary: #14490, #14491: add 'sundry'-style import tests for Tools/scripts. This patch changes a few of the scripts to have __name__=='__main__' clauses so that they are importable without running. Also fixes the syntax errors revealed by the tests. files: Lib/test/test_tools.py | 45 +++++++- Tools/scripts/abitype.py | 88 ++++++++------- Tools/scripts/find_recursionlimit.py | 24 ++-- Tools/scripts/findnocoding.py | 46 ++++---- Tools/scripts/fixcid.py | 2 +- Tools/scripts/md5sum.py | 2 +- Tools/scripts/parseentities.py | 3 +- 7 files changed, 128 insertions(+), 82 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -5,6 +5,7 @@ """ import os +import sys import unittest import sysconfig from test import support @@ -17,10 +18,11 @@ srcdir = sysconfig.get_config_var('projectbase') basepath = os.path.join(os.getcwd(), srcdir, 'Tools') +scriptsdir = os.path.join(basepath, 'scripts') class ReindentTests(unittest.TestCase): - script = os.path.join(basepath, 'scripts', 'reindent.py') + script = os.path.join(scriptsdir, 'reindent.py') def test_noargs(self): assert_python_ok(self.script) @@ -31,8 +33,47 @@ self.assertGreater(err, b'') +class TestSundryScripts(unittest.TestCase): + # At least make sure the rest don't have syntax errors. When tests are + # added for a script it should be added to the whitelist below. + + # scripts that have independent tests. + whitelist = ['reindent.py'] + # scripts that can't be imported without running + blacklist = ['make_ctype.py'] + # scripts that use windows-only modules + windows_only = ['win_add2path.py'] + # blacklisted for other reasons + other = ['analyze_dxp.py'] + + skiplist = blacklist + whitelist + windows_only + other + + def setUp(self): + cm = support.DirsOnSysPath(scriptsdir) + cm.__enter__() + self.addCleanup(cm.__exit__) + + def test_sundry(self): + for fn in os.listdir(scriptsdir): + if fn.endswith('.py') and fn not in self.skiplist: + __import__(fn[:-3]) + + @unittest.skipIf(sys.platform != "win32", "Windows-only test") + def test_sundry_windows(self): + for fn in self.windows_only: + __import__(fn[:-3]) + + def test_analyze_dxp_import(self): + if hasattr(sys, 'getdxp'): + import analyze_dxp + else: + with self.assertRaises(RuntimeError): + import analyze_dxp + + def test_main(): - support.run_unittest(ReindentTests) + support.run_unittest(*[obj for obj in globals().values() + if isinstance(obj, type)]) if __name__ == '__main__': diff --git a/Tools/scripts/abitype.py b/Tools/scripts/abitype.py --- a/Tools/scripts/abitype.py +++ b/Tools/scripts/abitype.py @@ -3,34 +3,6 @@ # Usage: abitype.py < old_code > new_code import re, sys -############ Simplistic C scanner ################################## -tokenizer = re.compile( - r"(?P#.*\n)" - r"|(?P/\*.*?\*/)" - r"|(?P[a-zA-Z_][a-zA-Z0-9_]*)" - r"|(?P[ \t\n]+)" - r"|(?P.)", - re.MULTILINE) - -tokens = [] -source = sys.stdin.read() -pos = 0 -while pos != len(source): - m = tokenizer.match(source, pos) - tokens.append([m.lastgroup, m.group()]) - pos += len(tokens[-1][1]) - if tokens[-1][0] == 'preproc': - # continuation lines are considered - # only in preprocess statements - while tokens[-1][1].endswith('\\\n'): - nl = source.find('\n', pos) - if nl == -1: - line = source[pos:] - else: - line = source[pos:nl+1] - tokens[-1][1] += line - pos += len(line) - ###### Replacement of PyTypeObject static instances ############## # classify each token, giving it a one-letter code: @@ -79,7 +51,7 @@ while tokens[pos][0] in ('ws', 'comment'): pos += 1 if tokens[pos][1] != 'PyVarObject_HEAD_INIT': - raise Exception, '%s has no PyVarObject_HEAD_INIT' % name + raise Exception('%s has no PyVarObject_HEAD_INIT' % name) while tokens[pos][1] != ')': pos += 1 pos += 1 @@ -183,18 +155,48 @@ return '\n'.join(res) -# Main loop: replace all static PyTypeObjects until -# there are none left. -while 1: - c = classify() - m = re.search('(SW)?TWIW?=W?{.*?};', c) - if not m: - break - start = m.start() - end = m.end() - name, fields = get_fields(start, m) - tokens[start:end] = [('',make_slots(name, fields))] +if __name__ == '__main__': -# Output result to stdout -for t, v in tokens: - sys.stdout.write(v) + ############ Simplistic C scanner ################################## + tokenizer = re.compile( + r"(?P#.*\n)" + r"|(?P/\*.*?\*/)" + r"|(?P[a-zA-Z_][a-zA-Z0-9_]*)" + r"|(?P[ \t\n]+)" + r"|(?P.)", + re.MULTILINE) + + tokens = [] + source = sys.stdin.read() + pos = 0 + while pos != len(source): + m = tokenizer.match(source, pos) + tokens.append([m.lastgroup, m.group()]) + pos += len(tokens[-1][1]) + if tokens[-1][0] == 'preproc': + # continuation lines are considered + # only in preprocess statements + while tokens[-1][1].endswith('\\\n'): + nl = source.find('\n', pos) + if nl == -1: + line = source[pos:] + else: + line = source[pos:nl+1] + tokens[-1][1] += line + pos += len(line) + + # Main loop: replace all static PyTypeObjects until + # there are none left. + while 1: + c = classify() + m = re.search('(SW)?TWIW?=W?{.*?};', c) + if not m: + break + start = m.start() + end = m.end() + name, fields = get_fields(start, m) + tokens[start:end] = [('',make_slots(name, fields))] + + # Output result to stdout + for t, v in tokens: + sys.stdout.write(v) diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py --- a/Tools/scripts/find_recursionlimit.py +++ b/Tools/scripts/find_recursionlimit.py @@ -106,14 +106,16 @@ else: print("Yikes!") -limit = 1000 -while 1: - check_limit(limit, "test_recurse") - check_limit(limit, "test_add") - check_limit(limit, "test_repr") - check_limit(limit, "test_init") - check_limit(limit, "test_getattr") - check_limit(limit, "test_getitem") - check_limit(limit, "test_cpickle") - print("Limit of %d is fine" % limit) - limit = limit + 100 +if __name__ == '__main__': + + limit = 1000 + while 1: + check_limit(limit, "test_recurse") + check_limit(limit, "test_add") + check_limit(limit, "test_repr") + check_limit(limit, "test_init") + check_limit(limit, "test_getattr") + check_limit(limit, "test_getitem") + check_limit(limit, "test_cpickle") + print("Limit of %d is fine" % limit) + limit = limit + 100 diff --git a/Tools/scripts/findnocoding.py b/Tools/scripts/findnocoding.py --- a/Tools/scripts/findnocoding.py +++ b/Tools/scripts/findnocoding.py @@ -76,29 +76,31 @@ -c: recognize Python source files trying to compile them -d: debug output""" % sys.argv[0] -try: - opts, args = getopt.getopt(sys.argv[1:], 'cd') -except getopt.error as msg: - print(msg, file=sys.stderr) - print(usage, file=sys.stderr) - sys.exit(1) +if __name__ == '__main__': -is_python = pysource.looks_like_python -debug = False + try: + opts, args = getopt.getopt(sys.argv[1:], 'cd') + except getopt.error as msg: + print(msg, file=sys.stderr) + print(usage, file=sys.stderr) + sys.exit(1) -for o, a in opts: - if o == '-c': - is_python = pysource.can_be_compiled - elif o == '-d': - debug = True + is_python = pysource.looks_like_python + debug = False -if not args: - print(usage, file=sys.stderr) - sys.exit(1) + for o, a in opts: + if o == '-c': + is_python = pysource.can_be_compiled + elif o == '-d': + debug = True -for fullpath in pysource.walk_python_files(args, is_python): - if debug: - print("Testing for coding: %s" % fullpath) - result = needs_declaration(fullpath) - if result: - print(fullpath) + if not args: + print(usage, file=sys.stderr) + sys.exit(1) + + for fullpath in pysource.walk_python_files(args, is_python): + if debug: + print("Testing for coding: %s" % fullpath) + result = needs_declaration(fullpath) + if result: + print(fullpath) diff --git a/Tools/scripts/fixcid.py b/Tools/scripts/fixcid.py --- a/Tools/scripts/fixcid.py +++ b/Tools/scripts/fixcid.py @@ -292,7 +292,7 @@ if not words: continue if len(words) == 3 and words[0] == 'struct': words[:2] = [words[0] + ' ' + words[1]] - elif len(words) <> 2: + elif len(words) != 2: err(substfile + '%s:%r: warning: bad line: %r' % (substfile, lineno, line)) continue if Reverse: diff --git a/Tools/scripts/md5sum.py b/Tools/scripts/md5sum.py --- a/Tools/scripts/md5sum.py +++ b/Tools/scripts/md5sum.py @@ -20,7 +20,7 @@ import sys import os import getopt -import md5 +from hashlib import md5 def sum(*files): sts = 0 diff --git a/Tools/scripts/parseentities.py b/Tools/scripts/parseentities.py --- a/Tools/scripts/parseentities.py +++ b/Tools/scripts/parseentities.py @@ -13,7 +13,6 @@ """ import re,sys -import TextTools entityRE = re.compile('') @@ -45,7 +44,7 @@ charcode = repr(charcode) else: charcode = repr(charcode) - comment = TextTools.collapse(comment) + comment = ' '.join(comment.split()) f.write(" '%s':\t%s, \t# %s\n" % (name,charcode,comment)) f.write('\n}\n') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 03:29:47 2012 From: python-checkins at python.org (r.david.murray) Date: Thu, 05 Apr 2012 03:29:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_=2314490=2C_=2314491=3A_add_=27sundry=27-style_import_?= =?utf8?q?tests_for_Tools/scripts=2E?= Message-ID: http://hg.python.org/cpython/rev/696cb524322a changeset: 76107:696cb524322a parent: 76105:fb907ee4fdfa parent: 76106:62dde5dd475e user: R David Murray date: Wed Apr 04 21:29:03 2012 -0400 summary: Merge #14490, #14491: add 'sundry'-style import tests for Tools/scripts. This patch changes a few of the scripts to have __name__=='__main__' clauses so that they are importable without running. Also fixes the syntax errors revealed by the tests. files: Lib/test/test_tools.py | 45 +++++++- Tools/scripts/abitype.py | 88 ++++++++------- Tools/scripts/find_recursionlimit.py | 24 ++-- Tools/scripts/findnocoding.py | 46 ++++---- Tools/scripts/fixcid.py | 2 +- Tools/scripts/md5sum.py | 2 +- Tools/scripts/parseentities.py | 3 +- 7 files changed, 128 insertions(+), 82 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -5,6 +5,7 @@ """ import os +import sys import unittest import sysconfig from test import support @@ -17,10 +18,11 @@ srcdir = sysconfig.get_config_var('projectbase') basepath = os.path.join(os.getcwd(), srcdir, 'Tools') +scriptsdir = os.path.join(basepath, 'scripts') class ReindentTests(unittest.TestCase): - script = os.path.join(basepath, 'scripts', 'reindent.py') + script = os.path.join(scriptsdir, 'reindent.py') def test_noargs(self): assert_python_ok(self.script) @@ -31,8 +33,47 @@ self.assertGreater(err, b'') +class TestSundryScripts(unittest.TestCase): + # At least make sure the rest don't have syntax errors. When tests are + # added for a script it should be added to the whitelist below. + + # scripts that have independent tests. + whitelist = ['reindent.py'] + # scripts that can't be imported without running + blacklist = ['make_ctype.py'] + # scripts that use windows-only modules + windows_only = ['win_add2path.py'] + # blacklisted for other reasons + other = ['analyze_dxp.py'] + + skiplist = blacklist + whitelist + windows_only + other + + def setUp(self): + cm = support.DirsOnSysPath(scriptsdir) + cm.__enter__() + self.addCleanup(cm.__exit__) + + def test_sundry(self): + for fn in os.listdir(scriptsdir): + if fn.endswith('.py') and fn not in self.skiplist: + __import__(fn[:-3]) + + @unittest.skipIf(sys.platform != "win32", "Windows-only test") + def test_sundry_windows(self): + for fn in self.windows_only: + __import__(fn[:-3]) + + def test_analyze_dxp_import(self): + if hasattr(sys, 'getdxp'): + import analyze_dxp + else: + with self.assertRaises(RuntimeError): + import analyze_dxp + + def test_main(): - support.run_unittest(ReindentTests) + support.run_unittest(*[obj for obj in globals().values() + if isinstance(obj, type)]) if __name__ == '__main__': diff --git a/Tools/scripts/abitype.py b/Tools/scripts/abitype.py --- a/Tools/scripts/abitype.py +++ b/Tools/scripts/abitype.py @@ -3,34 +3,6 @@ # Usage: abitype.py < old_code > new_code import re, sys -############ Simplistic C scanner ################################## -tokenizer = re.compile( - r"(?P#.*\n)" - r"|(?P/\*.*?\*/)" - r"|(?P[a-zA-Z_][a-zA-Z0-9_]*)" - r"|(?P[ \t\n]+)" - r"|(?P.)", - re.MULTILINE) - -tokens = [] -source = sys.stdin.read() -pos = 0 -while pos != len(source): - m = tokenizer.match(source, pos) - tokens.append([m.lastgroup, m.group()]) - pos += len(tokens[-1][1]) - if tokens[-1][0] == 'preproc': - # continuation lines are considered - # only in preprocess statements - while tokens[-1][1].endswith('\\\n'): - nl = source.find('\n', pos) - if nl == -1: - line = source[pos:] - else: - line = source[pos:nl+1] - tokens[-1][1] += line - pos += len(line) - ###### Replacement of PyTypeObject static instances ############## # classify each token, giving it a one-letter code: @@ -79,7 +51,7 @@ while tokens[pos][0] in ('ws', 'comment'): pos += 1 if tokens[pos][1] != 'PyVarObject_HEAD_INIT': - raise Exception, '%s has no PyVarObject_HEAD_INIT' % name + raise Exception('%s has no PyVarObject_HEAD_INIT' % name) while tokens[pos][1] != ')': pos += 1 pos += 1 @@ -183,18 +155,48 @@ return '\n'.join(res) -# Main loop: replace all static PyTypeObjects until -# there are none left. -while 1: - c = classify() - m = re.search('(SW)?TWIW?=W?{.*?};', c) - if not m: - break - start = m.start() - end = m.end() - name, fields = get_fields(start, m) - tokens[start:end] = [('',make_slots(name, fields))] +if __name__ == '__main__': -# Output result to stdout -for t, v in tokens: - sys.stdout.write(v) + ############ Simplistic C scanner ################################## + tokenizer = re.compile( + r"(?P#.*\n)" + r"|(?P/\*.*?\*/)" + r"|(?P[a-zA-Z_][a-zA-Z0-9_]*)" + r"|(?P[ \t\n]+)" + r"|(?P.)", + re.MULTILINE) + + tokens = [] + source = sys.stdin.read() + pos = 0 + while pos != len(source): + m = tokenizer.match(source, pos) + tokens.append([m.lastgroup, m.group()]) + pos += len(tokens[-1][1]) + if tokens[-1][0] == 'preproc': + # continuation lines are considered + # only in preprocess statements + while tokens[-1][1].endswith('\\\n'): + nl = source.find('\n', pos) + if nl == -1: + line = source[pos:] + else: + line = source[pos:nl+1] + tokens[-1][1] += line + pos += len(line) + + # Main loop: replace all static PyTypeObjects until + # there are none left. + while 1: + c = classify() + m = re.search('(SW)?TWIW?=W?{.*?};', c) + if not m: + break + start = m.start() + end = m.end() + name, fields = get_fields(start, m) + tokens[start:end] = [('',make_slots(name, fields))] + + # Output result to stdout + for t, v in tokens: + sys.stdout.write(v) diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py --- a/Tools/scripts/find_recursionlimit.py +++ b/Tools/scripts/find_recursionlimit.py @@ -106,14 +106,16 @@ else: print("Yikes!") -limit = 1000 -while 1: - check_limit(limit, "test_recurse") - check_limit(limit, "test_add") - check_limit(limit, "test_repr") - check_limit(limit, "test_init") - check_limit(limit, "test_getattr") - check_limit(limit, "test_getitem") - check_limit(limit, "test_cpickle") - print("Limit of %d is fine" % limit) - limit = limit + 100 +if __name__ == '__main__': + + limit = 1000 + while 1: + check_limit(limit, "test_recurse") + check_limit(limit, "test_add") + check_limit(limit, "test_repr") + check_limit(limit, "test_init") + check_limit(limit, "test_getattr") + check_limit(limit, "test_getitem") + check_limit(limit, "test_cpickle") + print("Limit of %d is fine" % limit) + limit = limit + 100 diff --git a/Tools/scripts/findnocoding.py b/Tools/scripts/findnocoding.py --- a/Tools/scripts/findnocoding.py +++ b/Tools/scripts/findnocoding.py @@ -76,29 +76,31 @@ -c: recognize Python source files trying to compile them -d: debug output""" % sys.argv[0] -try: - opts, args = getopt.getopt(sys.argv[1:], 'cd') -except getopt.error as msg: - print(msg, file=sys.stderr) - print(usage, file=sys.stderr) - sys.exit(1) +if __name__ == '__main__': -is_python = pysource.looks_like_python -debug = False + try: + opts, args = getopt.getopt(sys.argv[1:], 'cd') + except getopt.error as msg: + print(msg, file=sys.stderr) + print(usage, file=sys.stderr) + sys.exit(1) -for o, a in opts: - if o == '-c': - is_python = pysource.can_be_compiled - elif o == '-d': - debug = True + is_python = pysource.looks_like_python + debug = False -if not args: - print(usage, file=sys.stderr) - sys.exit(1) + for o, a in opts: + if o == '-c': + is_python = pysource.can_be_compiled + elif o == '-d': + debug = True -for fullpath in pysource.walk_python_files(args, is_python): - if debug: - print("Testing for coding: %s" % fullpath) - result = needs_declaration(fullpath) - if result: - print(fullpath) + if not args: + print(usage, file=sys.stderr) + sys.exit(1) + + for fullpath in pysource.walk_python_files(args, is_python): + if debug: + print("Testing for coding: %s" % fullpath) + result = needs_declaration(fullpath) + if result: + print(fullpath) diff --git a/Tools/scripts/fixcid.py b/Tools/scripts/fixcid.py --- a/Tools/scripts/fixcid.py +++ b/Tools/scripts/fixcid.py @@ -292,7 +292,7 @@ if not words: continue if len(words) == 3 and words[0] == 'struct': words[:2] = [words[0] + ' ' + words[1]] - elif len(words) <> 2: + elif len(words) != 2: err(substfile + '%s:%r: warning: bad line: %r' % (substfile, lineno, line)) continue if Reverse: diff --git a/Tools/scripts/md5sum.py b/Tools/scripts/md5sum.py --- a/Tools/scripts/md5sum.py +++ b/Tools/scripts/md5sum.py @@ -20,7 +20,7 @@ import sys import os import getopt -import md5 +from hashlib import md5 def sum(*files): sts = 0 diff --git a/Tools/scripts/parseentities.py b/Tools/scripts/parseentities.py --- a/Tools/scripts/parseentities.py +++ b/Tools/scripts/parseentities.py @@ -13,7 +13,6 @@ """ import re,sys -import TextTools entityRE = re.compile('') @@ -45,7 +44,7 @@ charcode = repr(charcode) else: charcode = repr(charcode) - comment = TextTools.collapse(comment) + comment = ' '.join(comment.split()) f.write(" '%s':\t%s, \t# %s\n" % (name,charcode,comment)) f.write('\n}\n') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 04:38:43 2012 From: python-checkins at python.org (r.david.murray) Date: Thu, 05 Apr 2012 04:38:43 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_test=5Ftools_fi?= =?utf8?q?x=3A_don=27t_import_analyze=5Fdxp_if_no_=5Fthread_module?= Message-ID: http://hg.python.org/cpython/rev/058f9a9f97cd changeset: 76108:058f9a9f97cd branch: 3.2 parent: 76106:62dde5dd475e user: R David Murray date: Wed Apr 04 22:37:50 2012 -0400 summary: test_tools fix: don't import analyze_dxp if no _thread module files: Lib/test/test_tools.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -63,6 +63,7 @@ for fn in self.windows_only: __import__(fn[:-3]) + @unittest.skipIf(not support.threading, "test requires _thread module") def test_analyze_dxp_import(self): if hasattr(sys, 'getdxp'): import analyze_dxp -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 04:38:43 2012 From: python-checkins at python.org (r.david.murray) Date: Thu, 05 Apr 2012 04:38:43 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge=3A_test=5Ftools_fix=3A_don=27t_import_analyze=5Fdxp_if?= =?utf8?q?_no_=5Fthread_module?= Message-ID: http://hg.python.org/cpython/rev/0da8ea486026 changeset: 76109:0da8ea486026 parent: 76107:696cb524322a parent: 76108:058f9a9f97cd user: R David Murray date: Wed Apr 04 22:38:26 2012 -0400 summary: Merge: test_tools fix: don't import analyze_dxp if no _thread module files: Lib/test/test_tools.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -63,6 +63,7 @@ for fn in self.windows_only: __import__(fn[:-3]) + @unittest.skipIf(not support.threading, "test requires _thread module") def test_analyze_dxp_import(self): if hasattr(sys, 'getdxp'): import analyze_dxp -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 04:42:51 2012 From: python-checkins at python.org (eli.bendersky) Date: Thu, 05 Apr 2012 04:42:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Replace_bootstrap_imports_w?= =?utf8?q?ith_real_C_API_calls=2E?= Message-ID: http://hg.python.org/cpython/rev/1ddf58262706 changeset: 76110:1ddf58262706 user: Eli Bendersky date: Thu Apr 05 05:40:58 2012 +0300 summary: Replace bootstrap imports with real C API calls. files: Modules/_elementtree.c | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -3034,8 +3034,7 @@ PyMODINIT_FUNC PyInit__elementtree(void) { - PyObject* m; - PyObject* g; + PyObject *m, *g, *temp; char* bootstrap; /* Initialize object types */ @@ -3067,10 +3066,6 @@ PyDict_SetItemString(g, "__builtins__", PyEval_GetBuiltins()); bootstrap = ( - - "from copy import deepcopy\n" - "from xml.etree import ElementPath\n" - "def iter(node, tag=None):\n" /* helper */ " if tag == '*':\n" " tag = None\n" @@ -3094,8 +3089,14 @@ if (!PyRun_String(bootstrap, Py_file_input, g, NULL)) return NULL; - elementpath_obj = PyDict_GetItemString(g, "ElementPath"); - elementtree_deepcopy_obj = PyDict_GetItemString(g, "deepcopy"); + if (!(temp = PyImport_ImportModule("copy"))) + return NULL; + elementtree_deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy"); + Py_XDECREF(temp); + + if (!(elementpath_obj = PyImport_ImportModule("xml.etree.ElementPath"))) + return NULL; + elementtree_iter_obj = PyDict_GetItemString(g, "iter"); elementtree_itertext_obj = PyDict_GetItemString(g, "itertext"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 05:02:33 2012 From: python-checkins at python.org (eric.araujo) Date: Thu, 05 Apr 2012 05:02:33 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_A_few_tweaks_to_whatsnew/3?= =?utf8?b?LjMgKGZpeGVzICMxNDM2Mik=?= Message-ID: http://hg.python.org/cpython/rev/deadd0823ab3 changeset: 76111:deadd0823ab3 user: ?ric Araujo date: Wed Apr 04 23:01:01 2012 -0400 summary: A few tweaks to whatsnew/3.3 (fixes #14362) files: Doc/whatsnew/3.3.rst | 49 ++++++++++++++++++++++++++----- Misc/NEWS | 4 +- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -574,6 +574,26 @@ The ``unicode_internal`` codec has been deprecated. + +collections +----------- + +Addition of a new :class:`~collections.ChainMap` class to allow treating a +number of mappings as a single unit. + +(Written by Raymond Hettinger for :issue:`11089`, made public in +:issue:`11297`) + +The abstract base classes have been moved in a new :mod:`collections.abc` +module, to better differentiate between the abstract and the concrete +collections classes. Aliases for ABCs are still present in the +:mod:`collections` module to preserve existing imports. + +(:issue:`11085`) + +.. XXX addition of __slots__ to ABCs not recorded here: internal detail + + crypt ----- @@ -867,11 +887,12 @@ --------- :mod:`distutils` has undergone additions and refactoring under a new name, -:mod:`packaging`, to allow developers to break backward compatibility. +:mod:`packaging`, to allow developers to make far-reaching changes without +being constrained by backward compatibility. :mod:`distutils` is still provided in the standard library, but users are encouraged to transition to :mod:`packaging`. For older versions of Python, a -backport compatible with 2.4+ and 3.1+ will be made available on PyPI under the -name :mod:`distutils2`. +backport compatible with Python 2.5 and newer and 3.2 is available on PyPI +under the name `distutils2 `_. .. TODO add examples and howto to the packaging docs and link to them @@ -1059,12 +1080,24 @@ (:issue:`1673007`) +webbrowser +---------- + +The :mod:`webbrowser` module supports more browsers: Google Chrome (named +:program:`chrome`, :program:`chromium`, :program:`chrome-browser` or +:program:`chromium-browser` depending on the version and operating system) as +well as the the generic launchers :program:`xdg-open` from the FreeDesktop.org +project and :program:`gvfs-open` which is the default URI handler for GNOME 3. + +(:issue:`13620` and :issue:`14493`) + + Optimizations ============= Major performance enhancements have been added: -* Thanks to the :pep:`393`, some operations on Unicode strings has been optimized: +* Thanks to :pep:`393`, some operations on Unicode strings have been optimized: * the memory footprint is divided by 2 to 4 depending on the text * encode an ASCII string to UTF-8 doesn't need to encode characters anymore, @@ -1083,7 +1116,7 @@ * :c:func:`PyMemoryView_FromMemory` -* The :pep:`393` added new Unicode types, macros and functions: +* :pep:`393` added new Unicode types, macros and functions: * High-level API: @@ -1126,7 +1159,7 @@ Deprecated Python modules, functions and methods ------------------------------------------------ -* The :mod:`distutils` modules has been deprecated. Use the new +* The :mod:`distutils` module has been deprecated. Use the new :mod:`packaging` module instead. * The ``unicode_internal`` codec has been deprecated because of the :pep:`393`, use UTF-8, UTF-16 (``utf-16-le`` or ``utf-16-be``), or UTF-32 @@ -1145,7 +1178,7 @@ Deprecated functions and types of the C API ------------------------------------------- -The :c:type:`Py_UNICODE` has been deprecated by the :pep:`393` and will be +The :c:type:`Py_UNICODE` has been deprecated by :pep:`393` and will be removed in Python 4. All functions using this type are deprecated: Unicode functions and methods using :c:type:`Py_UNICODE` and @@ -1247,7 +1280,7 @@ functions using this type are deprecated (but will stay available for at least five years). If you were using low-level Unicode APIs to construct and access unicode objects and you want to benefit of the - memory footprint reduction provided by the PEP 393, you have to convert + memory footprint reduction provided by PEP 393, you have to convert your code to the new :doc:`Unicode API <../c-api/unicode>`. However, if you only have been using high-level functions such as diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,7 +29,7 @@ a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. -- Issue #14493: Use gvfs-open/xdg-open in Lib/webbrowser.py. +- Issue #14493: Use gvfs-open or xdg-open in webbrowser. What's New in Python 3.3.0 Alpha 2? @@ -1007,7 +1007,7 @@ - Issue #11006: Don't issue low level warning in subprocess when pipe2() fails. -- Issue #13620: Support for Chrome browser in webbrowser.py Patch contributed +- Issue #13620: Support for Chrome browser in webbrowser. Patch contributed by Arnaud Calmettes. - Issue #11829: Fix code execution holes in inspect.getattr_static for -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Apr 5 05:35:22 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 05 Apr 2012 05:35:22 +0200 Subject: [Python-checkins] Daily reference leaks (696cb524322a): sum=4 Message-ID: results for 696cb524322a on branch "default" -------------------------------------------- test_support leaked [4, 0, 0] references, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog7IwXDg', '-x'] From python-checkins at python.org Thu Apr 5 05:44:41 2012 From: python-checkins at python.org (eli.bendersky) Date: Thu, 05 Apr 2012 05:44:41 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Reformat_by_replacing_tabs_?= =?utf8?q?with_4-spaces=2E_Makes_the_code_more_PEP-7_compliant?= Message-ID: http://hg.python.org/cpython/rev/64b8fdb0bfa9 changeset: 76112:64b8fdb0bfa9 user: Eli Bendersky date: Thu Apr 05 06:42:48 2012 +0300 summary: Reformat by replacing tabs with 4-spaces. Makes the code more PEP-7 compliant and gets rid of some gross formatting on tab=4-space-configured editors. files: Include/methodobject.h | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Include/methodobject.h b/Include/methodobject.h --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -17,7 +17,7 @@ typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *, - PyObject *); + PyObject *); typedef PyObject *(*PyNoArgsFunction)(PyObject *); PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *); @@ -33,22 +33,22 @@ (((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_STATIC ? \ NULL : ((PyCFunctionObject *)func) -> m_self) #define PyCFunction_GET_FLAGS(func) \ - (((PyCFunctionObject *)func) -> m_ml -> ml_flags) + (((PyCFunctionObject *)func) -> m_ml -> ml_flags) #endif PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); struct PyMethodDef { - const char *ml_name; /* The name of the built-in function/method */ - PyCFunction ml_meth; /* The C function that implements it */ - int ml_flags; /* Combination of METH_xxx flags, which mostly - describe the args expected by the C func */ - const char *ml_doc; /* The __doc__ attribute, or NULL */ + const char *ml_name; /* The name of the built-in function/method */ + PyCFunction ml_meth; /* The C function that implements it */ + int ml_flags; /* Combination of METH_xxx flags, which mostly + describe the args expected by the C func */ + const char *ml_doc; /* The __doc__ attribute, or NULL */ }; typedef struct PyMethodDef PyMethodDef; #define PyCFunction_New(ML, SELF) PyCFunction_NewEx((ML), (SELF), NULL) PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *, - PyObject *); + PyObject *); /* Flag passed to newmethodobject */ /* #define METH_OLDARGS 0x0000 -- unsupported now */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 09:04:32 2012 From: python-checkins at python.org (georg.brandl) Date: Thu, 05 Apr 2012 09:04:32 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Closes_=2314489?= =?utf8?q?=3A_correct_link_target=2E?= Message-ID: http://hg.python.org/cpython/rev/4416efeb0163 changeset: 76113:4416efeb0163 branch: 2.7 parent: 76104:9b472b24e5c9 user: Georg Brandl date: Thu Apr 05 09:04:40 2012 +0200 summary: Closes #14489: correct link target. files: Doc/library/functions.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -19,7 +19,7 @@ :func:`bytearray` :func:`float` :func:`list` :func:`raw_input` :func:`unichr` :func:`callable` :func:`format` :func:`locals` :func:`reduce` :func:`unicode` :func:`chr` :func:`frozenset` :func:`long` :func:`reload` :func:`vars` -:func:`classmethod` :func:`getattr` :func:`map` :func:`repr` :func:`xrange` +:func:`classmethod` :func:`getattr` :func:`map` :func:`.repr` :func:`xrange` :func:`cmp` :func:`globals` :func:`max` :func:`reversed` :func:`zip` :func:`compile` :func:`hasattr` :func:`memoryview` :func:`round` :func:`__import__` :func:`complex` :func:`hash` :func:`min` :func:`set` :func:`apply` -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 09:53:00 2012 From: python-checkins at python.org (georg.brandl) Date: Thu, 05 Apr 2012 09:53:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Replace_ThreadError_by_Runt?= =?utf8?q?imeError=3A_the_former_is_now_an_obsolete_alias_of_the?= Message-ID: http://hg.python.org/cpython/rev/f3dda6b66204 changeset: 76114:f3dda6b66204 parent: 76112:64b8fdb0bfa9 user: Georg Brandl date: Thu Apr 05 09:53:04 2012 +0200 summary: Replace ThreadError by RuntimeError: the former is now an obsolete alias of the latter. files: Doc/library/_thread.rst | 2 +- Doc/library/threading.rst | 2 +- 2 files changed, 2 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 @@ -94,7 +94,7 @@ *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 - unsupported, a :exc:`ThreadError` is raised. If the specified 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. 32kB is currently the minimum supported stack size value to guarantee sufficient stack space for the interpreter itself. Note that some platforms may have diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -174,7 +174,7 @@ *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 - unsupported, a :exc:`ThreadError` is raised. If the specified 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. 32kB is currently the minimum supported stack size value to guarantee sufficient stack space for the interpreter itself. Note that some platforms may have -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 11:41:48 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 05 Apr 2012 11:41:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=233033=3A_Add_displa?= =?utf8?q?yof_parameter_to_tkinter_font=2E?= Message-ID: http://hg.python.org/cpython/rev/774c2afa6665 changeset: 76115:774c2afa6665 user: Andrew Svetlov date: Thu Apr 05 12:41:20 2012 +0300 summary: Issue #3033: Add displayof parameter to tkinter font. Patch by Guilherme Polo. files: Lib/tkinter/font.py | 44 ++++++++++++++++++++------------ Misc/NEWS | 2 + 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/Lib/tkinter/font.py b/Lib/tkinter/font.py --- a/Lib/tkinter/font.py +++ b/Lib/tkinter/font.py @@ -2,9 +2,6 @@ # # written by Fredrik Lundh, February 1998 # -# FIXME: should add 'displayof' option where relevant (actual, families, -# measure, and metrics) -# __version__ = "0.9" @@ -124,14 +121,17 @@ "Return a distinct copy of the current font" return Font(self._root, **self.actual()) - def actual(self, option=None): + def actual(self, option=None, displayof=None): "Return actual font attributes" + args = () + if displayof: + args = ('-displayof', displayof) if option: - return self._call("font", "actual", self.name, "-"+option) + args = args + ('-' + option, ) + return self._call("font", "actual", self.name, *args) else: return self._mkdict( - self._split(self._call("font", "actual", self.name)) - ) + self._split(self._call("font", "actual", self.name, *args))) def cget(self, option): "Get font attribute" @@ -148,32 +148,42 @@ configure = config - def measure(self, text): + def measure(self, text, displayof=None): "Return text width" - return int(self._call("font", "measure", self.name, text)) + args = (text,) + if displayof: + args = ('-displayof', displayof, text) + return int(self._call("font", "measure", self.name, *args)) - def metrics(self, *options): + def metrics(self, *options, **kw): """Return font metrics. For best performance, create a dummy widget using this font before calling this method.""" - + args = () + displayof = kw.pop('displayof', None) + if displayof: + args = ('-displayof', displayof) if options: + args = args + self._get(options) return int( - self._call("font", "metrics", self.name, self._get(options))) + self._call("font", "metrics", self.name, *args)) else: - res = self._split(self._call("font", "metrics", self.name)) + res = self._split(self._call("font", "metrics", self.name, *args)) options = {} for i in range(0, len(res), 2): options[res[i][1:]] = int(res[i+1]) return options -def families(root=None): +def families(root=None, displayof=None): "Get font families (as a tuple)" if not root: root = tkinter._default_root - return root.tk.splitlist(root.tk.call("font", "families")) + args = () + if displayof: + args = ('-displayof', displayof) + return root.tk.splitlist(root.tk.call("font", "families", *args)) def names(root=None): @@ -205,10 +215,10 @@ print(f.measure("hello"), f.metrics("linespace")) - print(f.metrics()) + print(f.metrics(displayof=root)) f = Font(font=("Courier", 20, "bold")) - print(f.measure("hello"), f.metrics("linespace")) + print(f.measure("hello"), f.metrics("linespace", displayof=root)) w = tkinter.Label(root, text="Hello, world", font=f) w.pack() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,8 @@ Library ------- +- Issue #3033: Add displayof parameter to tkinter font. Patch by Guilherme Polo. + - Issue #14482: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_UNIX type address under Windows. Patch by Popa Claudiu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 13:44:33 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 05 Apr 2012 13:44:33 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Close_=2314249=3A_Use_an_un?= =?utf8?q?ion_instead_of_a_long_to_short_pointer_to_avoid_aliasing?= Message-ID: http://hg.python.org/cpython/rev/2c514c382a2a changeset: 76116:2c514c382a2a user: Victor Stinner date: Thu Apr 05 13:44:34 2012 +0200 summary: Close #14249: Use an union instead of a long to short pointer to avoid aliasing issue. Speed up UTF-16 by 20%. files: Objects/unicodeobject.c | 48 ++++++++++++++++------------ 1 files changed, 27 insertions(+), 21 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5496,33 +5496,39 @@ int kind = PyUnicode_KIND(unicode); void *data = PyUnicode_DATA(unicode); while (_q < aligned_end) { - unsigned long block = * (unsigned long *) _q; - unsigned short *pblock = (unsigned short*)█ + union { + unsigned long as_long; + unsigned short units[sizeof(long) / sizeof(short)]; + unsigned char bytes[sizeof(long)]; + } block, block_copy; Py_UCS4 maxch; + + block.as_long = *(unsigned long *) _q; if (native_ordering) { /* Can use buffer directly */ - if (block & FAST_CHAR_MASK) + if (block.as_long & FAST_CHAR_MASK) break; } else { /* Need to byte-swap */ - unsigned char *_p = (unsigned char*)pblock; - if (block & SWAPPED_FAST_CHAR_MASK) + block_copy = block; + + if (block.as_long & SWAPPED_FAST_CHAR_MASK) break; - _p[0] = _q[1]; - _p[1] = _q[0]; - _p[2] = _q[3]; - _p[3] = _q[2]; + block.bytes[0] = block_copy.bytes[1]; + block.bytes[1] = block_copy.bytes[0]; + block.bytes[2] = block_copy.bytes[3]; + block.bytes[3] = block_copy.bytes[2]; #if (SIZEOF_LONG == 8) - _p[4] = _q[5]; - _p[5] = _q[4]; - _p[6] = _q[7]; - _p[7] = _q[6]; -#endif - } - maxch = Py_MAX(pblock[0], pblock[1]); + block.bytes[4] = block_copy.bytes[5]; + block.bytes[5] = block_copy.bytes[4]; + block.bytes[6] = block_copy.bytes[7]; + block.bytes[7] = block_copy.bytes[6]; +#endif + } + maxch = Py_MAX(block.units[0], block.units[1]); #if SIZEOF_LONG == 8 - maxch = Py_MAX(maxch, Py_MAX(pblock[2], pblock[3])); + maxch = Py_MAX(maxch, Py_MAX(block.units[2], block.units[3])); #endif if (maxch > PyUnicode_MAX_CHAR_VALUE(unicode)) { if (unicode_widen(&unicode, maxch) < 0) @@ -5530,11 +5536,11 @@ kind = PyUnicode_KIND(unicode); data = PyUnicode_DATA(unicode); } - PyUnicode_WRITE(kind, data, outpos++, pblock[0]); - PyUnicode_WRITE(kind, data, outpos++, pblock[1]); + PyUnicode_WRITE(kind, data, outpos++, block.units[0]); + PyUnicode_WRITE(kind, data, outpos++, block.units[1]); #if SIZEOF_LONG == 8 - PyUnicode_WRITE(kind, data, outpos++, pblock[2]); - PyUnicode_WRITE(kind, data, outpos++, pblock[3]); + PyUnicode_WRITE(kind, data, outpos++, block.units[2]); + PyUnicode_WRITE(kind, data, outpos++, block.units[3]); #endif _q += SIZEOF_LONG; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 14:13:21 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 05 Apr 2012 14:13:21 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NTA1?= =?utf8?q?=3A_Fix_file_descriptor_leak_when_deallocating_file_objects_crea?= =?utf8?q?ted?= Message-ID: http://hg.python.org/cpython/rev/8258e5fa4a19 changeset: 76117:8258e5fa4a19 branch: 2.7 parent: 76113:4416efeb0163 user: Antoine Pitrou date: Thu Apr 05 14:07:52 2012 +0200 summary: Issue #14505: Fix file descriptor leak when deallocating file objects created with PyFile_FromString(). files: Misc/NEWS | 3 +++ Objects/fileobject.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ Core and Builtins ----------------- +- Issue #14505: Fix file descriptor leak when deallocating file objects + created with PyFile_FromString(). + - Issue #14474: Save and restore exception state in thread.start_new_thread() while writing error message if the thread leaves a unhandled exception. diff --git a/Objects/fileobject.c b/Objects/fileobject.c --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -493,9 +493,10 @@ PyObject * PyFile_FromString(char *name, char *mode) { + extern int fclose(FILE *); PyFileObject *f; - f = (PyFileObject *)PyFile_FromFile((FILE *)NULL, name, mode, NULL); + f = (PyFileObject *)PyFile_FromFile((FILE *)NULL, name, mode, fclose); if (f != NULL) { if (open_the_file(f, name, mode) == NULL) { Py_DECREF(f); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 15:58:38 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 05 Apr 2012 15:58:38 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NDk2?= =?utf8?q?=3A_Fix_wrong_name_in_idlelib/tabbedpages=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/f2dfe0ca6c21 changeset: 76118:f2dfe0ca6c21 branch: 3.2 parent: 76108:058f9a9f97cd user: Andrew Svetlov date: Thu Apr 05 16:58:05 2012 +0300 summary: Issue #14496: Fix wrong name in idlelib/tabbedpages.py. Patch by Popa Claudiu. files: Lib/idlelib/tabbedpages.py | 4 ++-- Misc/NEWS | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/tabbedpages.py b/Lib/idlelib/tabbedpages.py --- a/Lib/idlelib/tabbedpages.py +++ b/Lib/idlelib/tabbedpages.py @@ -78,7 +78,7 @@ def remove_tab(self, tab_name): """Remove the tab named """ if not tab_name in self._tab_names: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) self._tab_names.remove(tab_name) self._arrange_tabs() @@ -88,7 +88,7 @@ if tab_name == self._selected_tab: return if tab_name is not None and tab_name not in self._tabs: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) # deselect the current selected tab if self._selected_tab is not None: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,9 @@ Library ------- +- Issue #14496: Fix wrong name in idlelib/tabbedpages.py. + Patch by Popa Claudiu. + - Issue #14482: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_UNIX type address under Windows. Patch by Popa Claudiu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 16:04:38 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 05 Apr 2012 16:04:38 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_from_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/4be55684eefc changeset: 76119:4be55684eefc parent: 76116:2c514c382a2a parent: 76118:f2dfe0ca6c21 user: Andrew Svetlov date: Thu Apr 05 17:04:28 2012 +0300 summary: Merge from 3.2 files: Lib/idlelib/tabbedpages.py | 4 ++-- Misc/NEWS | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/tabbedpages.py b/Lib/idlelib/tabbedpages.py --- a/Lib/idlelib/tabbedpages.py +++ b/Lib/idlelib/tabbedpages.py @@ -78,7 +78,7 @@ def remove_tab(self, tab_name): """Remove the tab named """ if not tab_name in self._tab_names: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) self._tab_names.remove(tab_name) self._arrange_tabs() @@ -88,7 +88,7 @@ if tab_name == self._selected_tab: return if tab_name is not None and tab_name not in self._tabs: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) # deselect the current selected tab if self._selected_tab is not None: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #14496: Fix wrong name in idlelib/tabbedpages.py. + Patch by Popa Claudiu. + - Issue #3033: Add displayof parameter to tkinter font. Patch by Guilherme Polo. - Issue #14482: Raise a ValueError, not a NameError, when trying to create -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 16:27:26 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 05 Apr 2012 16:27:26 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Raise_InvalidOperation_if_e?= =?utf8?q?xponents_of_zeros_are_clamped_during_exact?= Message-ID: http://hg.python.org/cpython/rev/0f9d79998c79 changeset: 76120:0f9d79998c79 parent: 76116:2c514c382a2a user: Stefan Krah date: Thu Apr 05 15:21:58 2012 +0200 summary: Raise InvalidOperation if exponents of zeros are clamped during exact conversion in the Decimal constructor. Exact here refers to the representation and not to the value (clamping does not change the value). files: Lib/test/test_decimal.py | 24 ++++++++++++++++++ Modules/_decimal/_decimal.c | 4 +- Modules/_decimal/tests/deccheck.py | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -4953,6 +4953,30 @@ self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g') self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g') + def test_exact_conversion(self): + Decimal = C.Decimal + localcontext = C.localcontext + InvalidOperation = C.InvalidOperation + + with localcontext() as c: + + c.traps[InvalidOperation] = True + + # Clamped + x = "0e%d" % sys.maxsize + self.assertRaises(InvalidOperation, Decimal, x) + + x = "0e%d" % (-sys.maxsize-1) + self.assertRaises(InvalidOperation, Decimal, x) + + # Overflow + x = "1e%d" % sys.maxsize + self.assertRaises(InvalidOperation, Decimal, x) + + # Underflow + x = "1e%d" % (-sys.maxsize-1) + self.assertRaises(InvalidOperation, Decimal, x) + all_tests = [ CExplicitConstructionTest, PyExplicitConstructionTest, diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1935,7 +1935,7 @@ mpd_maxcontext(&maxctx); mpd_qset_string(MPD(dec), s, &maxctx, &status); - if (status & (MPD_Inexact|MPD_Rounded)) { + if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) { /* we want exact results */ mpd_seterror(MPD(dec), MPD_Invalid_operation, &status); } @@ -2139,7 +2139,7 @@ return NULL; } - if (status & (MPD_Inexact|MPD_Rounded)) { + if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) { /* we want exact results */ mpd_seterror(MPD(dec), MPD_Invalid_operation, &status); } diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py --- a/Modules/_decimal/tests/deccheck.py +++ b/Modules/_decimal/tests/deccheck.py @@ -302,6 +302,7 @@ dec = maxcontext.create_decimal(value) if maxcontext.flags[P.Inexact] or \ maxcontext.flags[P.Rounded] or \ + maxcontext.flags[P.Clamped] or \ maxcontext.flags[P.InvalidOperation]: return context.p._raise_error(P.InvalidOperation) if maxcontext.flags[P.FloatOperation]: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 16:27:27 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 05 Apr 2012 16:27:27 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Allow_printing_a_leading_?= =?utf8?q?=27-=27_and_the_maximum_number_of_exponent_digits?= Message-ID: http://hg.python.org/cpython/rev/a99cd3b98425 changeset: 76121:a99cd3b98425 user: Stefan Krah date: Thu Apr 05 15:46:19 2012 +0200 summary: Allow printing a leading '-' and the maximum number of exponent digits rather than raising RuntimeError (allocated space is sufficient for the additional character). files: Lib/test/test_decimal.py | 48 +++++++++++++++++++++++++ Modules/_decimal/_decimal.c | 4 +- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -4977,6 +4977,54 @@ x = "1e%d" % (-sys.maxsize-1) self.assertRaises(InvalidOperation, Decimal, x) + def test_from_tuple(self): + Decimal = C.Decimal + localcontext = C.localcontext + InvalidOperation = C.InvalidOperation + Overflow = C.Overflow + Underflow = C.Underflow + + with localcontext() as c: + + c.traps[InvalidOperation] = True + c.traps[Overflow] = True + c.traps[Underflow] = True + + # SSIZE_MAX + x = (1, (), sys.maxsize) + self.assertEqual(str(c.create_decimal(x)), '-0E+999999') + self.assertRaises(InvalidOperation, Decimal, x) + + x = (1, (0, 1, 2), sys.maxsize) + self.assertRaises(Overflow, c.create_decimal, x) + self.assertRaises(InvalidOperation, Decimal, x) + + # SSIZE_MIN + x = (1, (), -sys.maxsize-1) + self.assertEqual(str(c.create_decimal(x)), '-0E-1000026') + self.assertRaises(InvalidOperation, Decimal, x) + + x = (1, (0, 1, 2), -sys.maxsize-1) + self.assertRaises(Underflow, c.create_decimal, x) + self.assertRaises(InvalidOperation, Decimal, x) + + # OverflowError + x = (1, (), sys.maxsize+1) + self.assertRaises(OverflowError, c.create_decimal, x) + self.assertRaises(OverflowError, Decimal, x) + + x = (1, (), -sys.maxsize-2) + self.assertRaises(OverflowError, c.create_decimal, x) + self.assertRaises(OverflowError, Decimal, x) + + # Specials + x = (1, (), "N") + self.assertEqual(str(Decimal(x)), '-sNaN') + x = (1, (0,), "N") + self.assertEqual(str(Decimal(x)), '-sNaN') + x = (1, (0, 1), "N") + self.assertEqual(str(Decimal(x)), '-sNaN1') + all_tests = [ CExplicitConstructionTest, PyExplicitConstructionTest, diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2435,8 +2435,8 @@ if (sign_special[1] == '\0') { /* not a special number */ *cp++ = 'E'; - n = snprintf(cp, MPD_EXPDIGITS+1, "%" PRI_mpd_ssize_t, exp); - if (n < 0 || n >= MPD_EXPDIGITS+1) { + n = snprintf(cp, MPD_EXPDIGITS+2, "%" PRI_mpd_ssize_t, exp); + if (n < 0 || n >= MPD_EXPDIGITS+2) { PyErr_SetString(PyExc_RuntimeError, "internal error in dec_sequence_as_str"); goto error; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 16:27:27 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 05 Apr 2012 16:27:27 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Formatting=2E?= Message-ID: http://hg.python.org/cpython/rev/cd98afa9c4e9 changeset: 76122:cd98afa9c4e9 user: Stefan Krah date: Thu Apr 05 15:48:59 2012 +0200 summary: Formatting. files: Modules/_decimal/_decimal.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2385,8 +2385,8 @@ } /* coefficient */ - digits = sequence_as_tuple(PyTuple_GET_ITEM(dectuple, 1), - PyExc_ValueError, "coefficient must be a tuple of digits"); + digits = sequence_as_tuple(PyTuple_GET_ITEM(dectuple, 1), PyExc_ValueError, + "coefficient must be a tuple of digits"); if (digits == NULL) { goto error; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 16:27:28 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 05 Apr 2012 16:27:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Reduce_array_size=2E?= Message-ID: http://hg.python.org/cpython/rev/b33af0fb7bc6 changeset: 76123:b33af0fb7bc6 user: Stefan Krah date: Thu Apr 05 16:07:22 2012 +0200 summary: Reduce array size. files: Modules/_decimal/_decimal.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -4215,7 +4215,7 @@ mpd_uint_t p_data[1] = {2305843009213693951ULL}; mpd_t p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 19, 1, 1, p_data}; /* Inverse of 10 modulo p */ - mpd_uint_t inv10_p_data[2] = {2075258708292324556ULL}; + mpd_uint_t inv10_p_data[1] = {2075258708292324556ULL}; mpd_t inv10_p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 19, 1, 1, inv10_p_data}; #elif defined(CONFIG_32) && _PyHASH_BITS == 31 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 16:27:29 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 05 Apr 2012 16:27:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Whitespace=2E?= Message-ID: http://hg.python.org/cpython/rev/0375d3fa499c changeset: 76124:0375d3fa499c user: Stefan Krah date: Thu Apr 05 16:15:25 2012 +0200 summary: Whitespace. files: Modules/_decimal/_decimal.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -4934,7 +4934,7 @@ PyObject *result; CONVERT_OP_RAISE(&result, v, context); - return result; + return result; } static PyObject * -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 16:27:30 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 05 Apr 2012 16:27:30 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?b?KTogTWVyZ2Uu?= Message-ID: http://hg.python.org/cpython/rev/c5caaa83ca60 changeset: 76125:c5caaa83ca60 parent: 76124:0375d3fa499c parent: 76119:4be55684eefc user: Stefan Krah date: Thu Apr 05 16:25:21 2012 +0200 summary: Merge. files: Lib/idlelib/tabbedpages.py | 4 ++-- Misc/NEWS | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/tabbedpages.py b/Lib/idlelib/tabbedpages.py --- a/Lib/idlelib/tabbedpages.py +++ b/Lib/idlelib/tabbedpages.py @@ -78,7 +78,7 @@ def remove_tab(self, tab_name): """Remove the tab named """ if not tab_name in self._tab_names: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) self._tab_names.remove(tab_name) self._arrange_tabs() @@ -88,7 +88,7 @@ if tab_name == self._selected_tab: return if tab_name is not None and tab_name not in self._tabs: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) # deselect the current selected tab if self._selected_tab is not None: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #14496: Fix wrong name in idlelib/tabbedpages.py. + Patch by Popa Claudiu. + - Issue #3033: Add displayof parameter to tkinter font. Patch by Guilherme Polo. - Issue #14482: Raise a ValueError, not a NameError, when trying to create -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 20:55:20 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 05 Apr 2012 20:55:20 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=238515=3A_Set_=5F=5F?= =?utf8?q?file=5F=5F_when_run_file_in_IDLE=2E?= Message-ID: http://hg.python.org/cpython/rev/2c276d0553ff changeset: 76126:2c276d0553ff user: Andrew Svetlov date: Thu Apr 05 21:54:39 2012 +0300 summary: Issue #8515: Set __file__ when run file in IDLE. files: Lib/idlelib/NEWS.txt | 3 +++ Lib/idlelib/ScriptBinding.py | 12 ++++++------ Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,6 +1,9 @@ What's New in IDLE 3.3? ========================= +- Issue #8515: Set __file__ when run file in IDLE. + Initial patch by Bruce Frederiksen. + - IDLE can be launched as `python -m idlelib` - Issue #14409: IDLE now properly executes commands in the Shell window diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -150,16 +150,16 @@ dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: - _filename = %r + __file__ = {filename!r} import sys as _sys from os.path import basename as _basename if (not _sys.argv or - _basename(_sys.argv[0]) != _basename(_filename)): - _sys.argv = [_filename] + _basename(_sys.argv[0]) != _basename(__file__)): + _sys.argv = [__file__] import os as _os - _os.chdir(%r) - del _filename, _sys, _basename, _os - \n""" % (filename, dirname)) + _os.chdir({dirname!r}) + del _sys, _basename, _os + \n""".format(filename=filename, dirname=dirname)) interp.prepend_syspath(filename) # XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still # go to __stderr__. With subprocess, they go to the shell. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -333,6 +333,7 @@ John Fouhy Andrew Francis Martin Franklin +Bruce Frederiksen Robin Friedrich Ivan Frohne Matthias Fuchs diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #8515: Set __file__ when run file in IDLE. + Initial patch by Bruce Frederiksen. + - Issue #14496: Fix wrong name in idlelib/tabbedpages.py. Patch by Popa Claudiu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 22:31:29 2012 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 05 Apr 2012 22:31:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Clarify_that_the_purpose_of?= =?utf8?q?_computing_all_the_miscellaneous_collection_types_is?= Message-ID: http://hg.python.org/cpython/rev/67c26185636b changeset: 76127:67c26185636b user: Raymond Hettinger date: Thu Apr 05 13:31:12 2012 -0700 summary: Clarify that the purpose of computing all the miscellaneous collection types is to register them with the appropriate ABCs. files: Lib/collections/abc.py | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Lib/collections/abc.py b/Lib/collections/abc.py --- a/Lib/collections/abc.py +++ b/Lib/collections/abc.py @@ -18,9 +18,13 @@ "ByteString", ] - -### collection related types which are not exposed through builtin ### -## iterators ## +# Private list of types that we want to register with the various ABCs +# so that they will pass tests like: +# it = iter(somebytearray) +# assert isinstance(it, Iterable) +# Note: in other implementations, these types many not be distinct +# and they make have their own implementation specific types that +# are not included on this list. bytes_iterator = type(iter(b'')) bytearray_iterator = type(iter(bytearray())) #callable_iterator = ??? -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 22:54:47 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 05 Apr 2012 22:54:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Close_=2314249=3A_Use_bit_s?= =?utf8?q?hifts_instead_of_an_union=2C_it=27s_more_efficient=2E?= Message-ID: http://hg.python.org/cpython/rev/489f252b1f8b changeset: 76128:489f252b1f8b user: Victor Stinner date: Thu Apr 05 22:54:49 2012 +0200 summary: Close #14249: Use bit shifts instead of an union, it's more efficient. Patch written by Serhiy Storchaka files: Misc/ACKS | 1 + Objects/unicodeobject.c | 63 ++++++++++++++++------------ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -977,6 +977,7 @@ Peter Stoehr Casper Stoel Michael Stone +Serhiy Storchaka Ken Stox Dan Stromberg Daniel Stutzbach diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5393,9 +5393,11 @@ #if (SIZEOF_LONG == 8) # define FAST_CHAR_MASK 0x8000800080008000L # define SWAPPED_FAST_CHAR_MASK 0x0080008000800080L +# define STRIPPED_MASK 0x00FF00FF00FF00FFL #elif (SIZEOF_LONG == 4) # define FAST_CHAR_MASK 0x80008000L # define SWAPPED_FAST_CHAR_MASK 0x00800080L +# define STRIPPED_MASK 0x00FF00FFL #else # error C 'long' size should be either 4 or 8! #endif @@ -5496,39 +5498,31 @@ int kind = PyUnicode_KIND(unicode); void *data = PyUnicode_DATA(unicode); while (_q < aligned_end) { - union { - unsigned long as_long; - unsigned short units[sizeof(long) / sizeof(short)]; - unsigned char bytes[sizeof(long)]; - } block, block_copy; + unsigned long block = * (unsigned long *) _q; Py_UCS4 maxch; - - block.as_long = *(unsigned long *) _q; if (native_ordering) { /* Can use buffer directly */ - if (block.as_long & FAST_CHAR_MASK) + if (block & FAST_CHAR_MASK) break; } else { /* Need to byte-swap */ - block_copy = block; - - if (block.as_long & SWAPPED_FAST_CHAR_MASK) + if (block & SWAPPED_FAST_CHAR_MASK) break; - block.bytes[0] = block_copy.bytes[1]; - block.bytes[1] = block_copy.bytes[0]; - block.bytes[2] = block_copy.bytes[3]; - block.bytes[3] = block_copy.bytes[2]; -#if (SIZEOF_LONG == 8) - block.bytes[4] = block_copy.bytes[5]; - block.bytes[5] = block_copy.bytes[4]; - block.bytes[6] = block_copy.bytes[7]; - block.bytes[7] = block_copy.bytes[6]; -#endif - } - maxch = Py_MAX(block.units[0], block.units[1]); + block = ((block >> 8) & STRIPPED_MASK) | + ((block & STRIPPED_MASK) << 8); + } + maxch = (Py_UCS2)(block & 0xFFFF); #if SIZEOF_LONG == 8 - maxch = Py_MAX(maxch, Py_MAX(block.units[2], block.units[3])); + ch = (Py_UCS2)((block >> 16) & 0xFFFF); + maxch = Py_MAX(maxch, ch); + ch = (Py_UCS2)((block >> 32) & 0xFFFF); + maxch = Py_MAX(maxch, ch); + ch = (Py_UCS2)(block >> 48); + maxch = Py_MAX(maxch, ch); +#else + ch = (Py_UCS2)(block >> 16); + maxch = Py_MAX(maxch, ch); #endif if (maxch > PyUnicode_MAX_CHAR_VALUE(unicode)) { if (unicode_widen(&unicode, maxch) < 0) @@ -5536,11 +5530,24 @@ kind = PyUnicode_KIND(unicode); data = PyUnicode_DATA(unicode); } - PyUnicode_WRITE(kind, data, outpos++, block.units[0]); - PyUnicode_WRITE(kind, data, outpos++, block.units[1]); +#ifdef BYTEORDER_IS_LITTLE_ENDIAN + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block & 0xFFFF)); #if SIZEOF_LONG == 8 - PyUnicode_WRITE(kind, data, outpos++, block.units[2]); - PyUnicode_WRITE(kind, data, outpos++, block.units[3]); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 16) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 32) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 48))); +#else + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block >> 16)); +#endif +#else +#if SIZEOF_LONG == 8 + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 48))); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 32) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 16) & 0xFFFF)); +#else + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block >> 16)); +#endif + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block & 0xFFFF)); #endif _q += SIZEOF_LONG; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 23:01:58 2012 From: python-checkins at python.org (sandro.tosi) Date: Thu, 05 Apr 2012 23:01:58 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NTAy?= =?utf8?q?=3A_release=28=29_and_unlocked_lock_generates_a_ThreadError?= Message-ID: http://hg.python.org/cpython/rev/efeca6ff2751 changeset: 76129:efeca6ff2751 branch: 2.7 parent: 76117:8258e5fa4a19 user: Sandro Tosi date: Thu Apr 05 22:51:00 2012 +0200 summary: Issue #14502: release() and unlocked lock generates a ThreadError files: Doc/library/threading.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -420,7 +420,7 @@ are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed. - Do not call this method when the lock is unlocked. + When invoked on an unlocked lock, a :exc:`ThreadError` is raised. There is no return value. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 23:01:58 2012 From: python-checkins at python.org (sandro.tosi) Date: Thu, 05 Apr 2012 23:01:58 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NTAy?= =?utf8?q?=3A_release=28=29_and_unlocked_lock_generates_a_ThreadError?= Message-ID: http://hg.python.org/cpython/rev/acea9d95a6d8 changeset: 76130:acea9d95a6d8 branch: 3.2 parent: 76118:f2dfe0ca6c21 user: Sandro Tosi date: Thu Apr 05 22:51:54 2012 +0200 summary: Issue #14502: release() and unlocked lock generates a ThreadError files: Doc/library/threading.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -430,7 +430,7 @@ are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed. - Do not call this method when the lock is unlocked. + When invoked on an unlocked lock, a :exc:`ThreadError` is raised. There is no return value. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 23:01:59 2012 From: python-checkins at python.org (sandro.tosi) Date: Thu, 05 Apr 2012 23:01:59 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314502=3A_merge_wit?= =?utf8?q?h_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/c10a0f93544e changeset: 76131:c10a0f93544e parent: 76127:67c26185636b user: Sandro Tosi date: Thu Apr 05 22:53:21 2012 +0200 summary: Issue #14502: merge with 3.2 files: Doc/library/threading.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -452,7 +452,7 @@ are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed. - Do not call this method when the lock is unlocked. + When invoked on an unlocked lock, a :exc:`RuntimeError` is raised. There is no return value. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 5 23:02:00 2012 From: python-checkins at python.org (sandro.tosi) Date: Thu, 05 Apr 2012 23:02:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/ec3e0f1a3b8d changeset: 76132:ec3e0f1a3b8d parent: 76131:c10a0f93544e parent: 76128:489f252b1f8b user: Sandro Tosi date: Thu Apr 05 22:59:41 2012 +0200 summary: merge heads files: Misc/ACKS | 1 + Objects/unicodeobject.c | 63 ++++++++++++++++------------ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -977,6 +977,7 @@ Peter Stoehr Casper Stoel Michael Stone +Serhiy Storchaka Ken Stox Dan Stromberg Daniel Stutzbach diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5393,9 +5393,11 @@ #if (SIZEOF_LONG == 8) # define FAST_CHAR_MASK 0x8000800080008000L # define SWAPPED_FAST_CHAR_MASK 0x0080008000800080L +# define STRIPPED_MASK 0x00FF00FF00FF00FFL #elif (SIZEOF_LONG == 4) # define FAST_CHAR_MASK 0x80008000L # define SWAPPED_FAST_CHAR_MASK 0x00800080L +# define STRIPPED_MASK 0x00FF00FFL #else # error C 'long' size should be either 4 or 8! #endif @@ -5496,39 +5498,31 @@ int kind = PyUnicode_KIND(unicode); void *data = PyUnicode_DATA(unicode); while (_q < aligned_end) { - union { - unsigned long as_long; - unsigned short units[sizeof(long) / sizeof(short)]; - unsigned char bytes[sizeof(long)]; - } block, block_copy; + unsigned long block = * (unsigned long *) _q; Py_UCS4 maxch; - - block.as_long = *(unsigned long *) _q; if (native_ordering) { /* Can use buffer directly */ - if (block.as_long & FAST_CHAR_MASK) + if (block & FAST_CHAR_MASK) break; } else { /* Need to byte-swap */ - block_copy = block; - - if (block.as_long & SWAPPED_FAST_CHAR_MASK) + if (block & SWAPPED_FAST_CHAR_MASK) break; - block.bytes[0] = block_copy.bytes[1]; - block.bytes[1] = block_copy.bytes[0]; - block.bytes[2] = block_copy.bytes[3]; - block.bytes[3] = block_copy.bytes[2]; -#if (SIZEOF_LONG == 8) - block.bytes[4] = block_copy.bytes[5]; - block.bytes[5] = block_copy.bytes[4]; - block.bytes[6] = block_copy.bytes[7]; - block.bytes[7] = block_copy.bytes[6]; -#endif - } - maxch = Py_MAX(block.units[0], block.units[1]); + block = ((block >> 8) & STRIPPED_MASK) | + ((block & STRIPPED_MASK) << 8); + } + maxch = (Py_UCS2)(block & 0xFFFF); #if SIZEOF_LONG == 8 - maxch = Py_MAX(maxch, Py_MAX(block.units[2], block.units[3])); + ch = (Py_UCS2)((block >> 16) & 0xFFFF); + maxch = Py_MAX(maxch, ch); + ch = (Py_UCS2)((block >> 32) & 0xFFFF); + maxch = Py_MAX(maxch, ch); + ch = (Py_UCS2)(block >> 48); + maxch = Py_MAX(maxch, ch); +#else + ch = (Py_UCS2)(block >> 16); + maxch = Py_MAX(maxch, ch); #endif if (maxch > PyUnicode_MAX_CHAR_VALUE(unicode)) { if (unicode_widen(&unicode, maxch) < 0) @@ -5536,11 +5530,24 @@ kind = PyUnicode_KIND(unicode); data = PyUnicode_DATA(unicode); } - PyUnicode_WRITE(kind, data, outpos++, block.units[0]); - PyUnicode_WRITE(kind, data, outpos++, block.units[1]); +#ifdef BYTEORDER_IS_LITTLE_ENDIAN + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block & 0xFFFF)); #if SIZEOF_LONG == 8 - PyUnicode_WRITE(kind, data, outpos++, block.units[2]); - PyUnicode_WRITE(kind, data, outpos++, block.units[3]); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 16) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 32) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 48))); +#else + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block >> 16)); +#endif +#else +#if SIZEOF_LONG == 8 + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 48))); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 32) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 16) & 0xFFFF)); +#else + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block >> 16)); +#endif + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block & 0xFFFF)); #endif _q += SIZEOF_LONG; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 04:57:17 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 04:57:17 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/9506e636bd9f changeset: 76133:9506e636bd9f parent: 76132:ec3e0f1a3b8d parent: 76130:acea9d95a6d8 user: Benjamin Peterson date: Thu Apr 05 22:57:10 2012 -0400 summary: merge 3.2 files: Doc/library/threading.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -452,7 +452,7 @@ are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed. - When invoked on an unlocked lock, a :exc:`RuntimeError` is raised. + When invoked on an unlocked lock, a :exc:`ThreadError` is raised. There is no return value. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 05:01:28 2012 From: python-checkins at python.org (r.david.murray) Date: Fri, 06 Apr 2012 05:01:28 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NDkyOiBmaXgg?= =?utf8?q?some_bugs_in_Tools/scripts/pdeps=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/e9b8115c5b25 changeset: 76134:e9b8115c5b25 branch: 3.2 parent: 76130:acea9d95a6d8 user: R David Murray date: Thu Apr 05 22:59:13 2012 -0400 summary: #14492: fix some bugs in Tools/scripts/pdeps.py. Initial patch by Popa Claudiu. files: Lib/test/test_tools.py | 27 +++++++++++++++++++++++++++ Tools/scripts/pdeps.py | 10 +++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -6,8 +6,10 @@ import os import sys +import imp import unittest import sysconfig +import tempfile from test import support from test.script_helper import assert_python_ok @@ -72,6 +74,31 @@ import analyze_dxp +class PdepsTests(unittest.TestCase): + + @classmethod + def setUpClass(self): + path = os.path.join(scriptsdir, 'pdeps.py') + self.pdeps = imp.load_source('pdeps', path) + + @classmethod + def tearDownClass(self): + if 'pdeps' in sys.modules: + del sys.modules['pdeps'] + + def test_process_errors(self): + # Issue #14492: m_import.match(line) can be None. + with tempfile.TemporaryDirectory() as tmpdir: + fn = os.path.join(tmpdir, 'foo') + with open(fn, 'w') as stream: + stream.write("#!/this/will/fail") + self.pdeps.process(fn, {}) + + def test_inverse_attribute_error(self): + # Issue #14492: this used to fail with an AttributeError. + self.pdeps.inverse({'a': []}) + + def test_main(): support.run_unittest(*[obj for obj in globals().values() if isinstance(obj, type)]) diff --git a/Tools/scripts/pdeps.py b/Tools/scripts/pdeps.py --- a/Tools/scripts/pdeps.py +++ b/Tools/scripts/pdeps.py @@ -76,10 +76,9 @@ nextline = fp.readline() if not nextline: break line = line[:-1] + nextline - if m_import.match(line) >= 0: - (a, b), (a1, b1) = m_import.regs[:2] - elif m_from.match(line) >= 0: - (a, b), (a1, b1) = m_from.regs[:2] + m_found = m_import.match(line) or m_from.match(line) + if m_found: + (a, b), (a1, b1) = m_found.regs[:2] else: continue words = line[a1:b1].split(',') # print '#', line, words @@ -87,6 +86,7 @@ word = word.strip() if word not in list: list.append(word) + fp.close() # Compute closure (this is in fact totally general) @@ -123,7 +123,7 @@ def inverse(table): inv = {} for key in table.keys(): - if not inv.has_key(key): + if key not in inv: inv[key] = [] for item in table[key]: store(inv, item, key) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 05:01:29 2012 From: python-checkins at python.org (r.david.murray) Date: Fri, 06 Apr 2012 05:01:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_=2314492=3A_fix_some_bugs_in_Tools/scripts/pdeps=2Epy?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/26a7cc129b3d changeset: 76135:26a7cc129b3d parent: 76133:9506e636bd9f parent: 76134:e9b8115c5b25 user: R David Murray date: Thu Apr 05 23:01:13 2012 -0400 summary: Merge #14492: fix some bugs in Tools/scripts/pdeps.py. Initial patch by Popa Claudiu. files: Lib/test/test_tools.py | 27 +++++++++++++++++++++++++++ Tools/scripts/pdeps.py | 10 +++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -6,8 +6,10 @@ import os import sys +import imp import unittest import sysconfig +import tempfile from test import support from test.script_helper import assert_python_ok @@ -72,6 +74,31 @@ import analyze_dxp +class PdepsTests(unittest.TestCase): + + @classmethod + def setUpClass(self): + path = os.path.join(scriptsdir, 'pdeps.py') + self.pdeps = imp.load_source('pdeps', path) + + @classmethod + def tearDownClass(self): + if 'pdeps' in sys.modules: + del sys.modules['pdeps'] + + def test_process_errors(self): + # Issue #14492: m_import.match(line) can be None. + with tempfile.TemporaryDirectory() as tmpdir: + fn = os.path.join(tmpdir, 'foo') + with open(fn, 'w') as stream: + stream.write("#!/this/will/fail") + self.pdeps.process(fn, {}) + + def test_inverse_attribute_error(self): + # Issue #14492: this used to fail with an AttributeError. + self.pdeps.inverse({'a': []}) + + def test_main(): support.run_unittest(*[obj for obj in globals().values() if isinstance(obj, type)]) diff --git a/Tools/scripts/pdeps.py b/Tools/scripts/pdeps.py --- a/Tools/scripts/pdeps.py +++ b/Tools/scripts/pdeps.py @@ -76,10 +76,9 @@ nextline = fp.readline() if not nextline: break line = line[:-1] + nextline - if m_import.match(line) >= 0: - (a, b), (a1, b1) = m_import.regs[:2] - elif m_from.match(line) >= 0: - (a, b), (a1, b1) = m_from.regs[:2] + m_found = m_import.match(line) or m_from.match(line) + if m_found: + (a, b), (a1, b1) = m_found.regs[:2] else: continue words = line[a1:b1].split(',') # print '#', line, words @@ -87,6 +86,7 @@ word = word.strip() if word not in list: list.append(word) + fp.close() # Compute closure (this is in fact totally general) @@ -123,7 +123,7 @@ def inverse(table): inv = {} for key in table.keys(): - if not inv.has_key(key): + if key not in inv: inv[key] = [] for item in table[key]: store(inv, item, key) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Apr 6 05:40:39 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 06 Apr 2012 05:40:39 +0200 Subject: [Python-checkins] Daily reference leaks (ec3e0f1a3b8d): sum=0 Message-ID: results for ec3e0f1a3b8d on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogIoG1k1', '-x'] From python-checkins at python.org Fri Apr 6 11:15:48 2012 From: python-checkins at python.org (sandro.tosi) Date: Fri, 06 Apr 2012 11:15:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314502=3A_it=27s_Ru?= =?utf8?q?ntimeError_on_3=2E3?= Message-ID: http://hg.python.org/cpython/rev/068a614e9d97 changeset: 76136:068a614e9d97 user: Sandro Tosi date: Fri Apr 06 11:15:06 2012 +0200 summary: Issue #14502: it's RuntimeError on 3.3 files: Doc/library/threading.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -452,7 +452,7 @@ are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed. - When invoked on an unlocked lock, a :exc:`ThreadError` is raised. + When invoked on an unlocked lock, a :exc:`RuntimeError` is raised. There is no return value. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 16:42:06 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Fri, 06 Apr 2012 16:42:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Set_a_time_threshold_in_tes?= =?utf8?q?t=5Fasyncore=2Ecapture=5Fserver_so_that_tests_don=27t?= Message-ID: http://hg.python.org/cpython/rev/d8c5c0f7aa56 changeset: 76137:d8c5c0f7aa56 user: Kristj?n Valur J?nsson date: Fri Apr 06 14:37:45 2012 +0000 summary: Set a time threshold in test_asyncore.capture_server so that tests don't deadlock if the main thread fails before sending all the data. files: Lib/test/test_asyncore.py | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -74,15 +74,16 @@ pass else: n = 200 - while n > 0: - r, w, e = select.select([conn], [], []) + start = time.time() + while n > 0 and time.time() - start < 3.0: + r, w, e = select.select([conn], [], [], 0.1) if r: + n -= 1 data = conn.recv(10) # keep everything except for the newline terminator buf.write(data.replace(b'\n', b'')) if b'\n' in data: break - n -= 1 time.sleep(0.01) conn.close() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 18:55:29 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 06 Apr 2012 18:55:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_test=5Fsite_from_modify?= =?utf8?q?ing_sysconfig=2E=5FCONFIG=5FVARS=2E?= Message-ID: http://hg.python.org/cpython/rev/1a3eb3b8ba42 changeset: 76138:1a3eb3b8ba42 parent: 76082:d0e4e3ef224e user: Brett Cannon date: Wed Apr 04 17:31:16 2012 -0400 summary: Fix test_site from modifying sysconfig._CONFIG_VARS. files: Lib/test/test_site.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -39,6 +39,7 @@ self.old_base = site.USER_BASE self.old_site = site.USER_SITE self.old_prefixes = site.PREFIXES + self.original_vars = sysconfig._CONFIG_VARS self.old_vars = copy(sysconfig._CONFIG_VARS) def tearDown(self): @@ -47,7 +48,9 @@ site.USER_BASE = self.old_base site.USER_SITE = self.old_site site.PREFIXES = self.old_prefixes - sysconfig._CONFIG_VARS = self.old_vars + sysconfig._CONFIG_VARS = self.original_vars + sysconfig._CONFIG_VARS.clear() + sysconfig._CONFIG_VARS.update(self.old_vars) def test_makepath(self): # Test makepath() have an absolute path for its first return value -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 18:55:30 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 06 Apr 2012 18:55:30 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/fbbb14604e94 changeset: 76139:fbbb14604e94 parent: 76138:1a3eb3b8ba42 parent: 76137:d8c5c0f7aa56 user: Brett Cannon date: Fri Apr 06 12:54:57 2012 -0400 summary: merge files: .bzrignore | 1 - .gitignore | 1 - .hgignore | 1 - Doc/library/_thread.rst | 2 +- Doc/library/collections.rst | 4 +- Doc/library/subprocess.rst | 2 +- Doc/library/threading.rst | 4 +- Doc/whatsnew/3.3.rst | 51 +- Include/methodobject.h | 16 +- Include/object.h | 5 + Lib/collections/abc.py | 10 +- Lib/idlelib/NEWS.txt | 3 + Lib/idlelib/ScriptBinding.py | 12 +- Lib/idlelib/tabbedpages.py | 4 +- Lib/multiprocessing/connection.py | 4 + Lib/test/seq_tests.py | 7 + Lib/test/test_array.py | 14 + Lib/test/test_asyncore.py | 7 +- Lib/test/test_builtin.py | 41 + Lib/test/test_bytes.py | 18 + Lib/test/test_decimal.py | 72 + Lib/test/test_deque.py | 13 + Lib/test/test_dict.py | 54 + Lib/test/test_enumerate.py | 30 +- Lib/test/test_iter.py | 43 +- Lib/test/test_itertools.py | 386 ++++++- Lib/test/test_list.py | 28 + Lib/test/test_multiprocessing.py | 4 + Lib/test/test_range.py | 24 +- Lib/test/test_set.py | 21 + Lib/test/test_tools.py | 73 +- Lib/test/test_tuple.py | 29 + Lib/test/test_xml_etree.py | 35 + Lib/tkinter/font.py | 63 +- Lib/tkinter/ttk.py | 2 +- Lib/webbrowser.py | 8 + Makefile.pre.in | 2 +- Misc/ACKS | 2 + Misc/NEWS | 20 +- Modules/_collectionsmodule.c | 93 +- Modules/_decimal/_decimal.c | 16 +- Modules/_decimal/tests/deccheck.py | 1 + Modules/_elementtree.c | 88 +- Modules/arraymodule.c | 30 +- Modules/itertoolsmodule.c | 890 ++++++++++++++- Objects/bytearrayobject.c | 36 +- Objects/bytesobject.c | 34 + Objects/dictobject.c | 53 + Objects/enumobject.c | 50 +- Objects/iterobject.c | 47 +- Objects/listobject.c | 80 + Objects/object.c | 13 + Objects/rangeobject.c | 92 + Objects/setobject.c | 45 +- Objects/tupleobject.c | 31 + Objects/unicodeobject.c | 85 +- Python/bltinmodule.c | 56 +- Python/pythonrun.c | 57 +- Tools/scripts/abitype.py | 88 +- Tools/scripts/find_recursionlimit.py | 24 +- Tools/scripts/findnocoding.py | 46 +- Tools/scripts/fixcid.py | 2 +- Tools/scripts/md5sum.py | 2 +- Tools/scripts/parseentities.py | 3 +- Tools/scripts/pdeps.py | 10 +- 65 files changed, 2751 insertions(+), 337 deletions(-) diff --git a/.bzrignore b/.bzrignore --- a/.bzrignore +++ b/.bzrignore @@ -33,7 +33,6 @@ Modules/config.c Modules/ld_so_aix Parser/pgen -Parser/pgen.stamp Lib/test/data/* Lib/lib2to3/Grammar*.pickle Lib/lib2to3/PatternGrammar*.pickle diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ PCbuild/*.pdb PCbuild/Win32-temp-* Parser/pgen -Parser/pgen.stamp __pycache__ autom4te.cache build/ diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -32,7 +32,6 @@ Modules/config.c Modules/ld_so_aix$ Parser/pgen$ -Parser/pgen.stamp$ PCbuild/amd64/ ^core ^python-gdb.py diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst --- a/Doc/library/_thread.rst +++ b/Doc/library/_thread.rst @@ -94,7 +94,7 @@ *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 - unsupported, a :exc:`ThreadError` is raised. If the specified 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. 32kB is currently the minimum supported stack size value to guarantee sufficient stack space for the interpreter itself. Note that some platforms may have diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -41,6 +41,8 @@ :class:`ChainMap` objects ------------------------- +.. versionadded:: 3.3 + A :class:`ChainMap` class is provided for quickly linking a number of mappings so they can be treated as a single unit. It is often much faster than creating a new dictionary and running multiple :meth:`~dict.update` calls. @@ -91,8 +93,6 @@ The use-cases also parallel those for the builtin :func:`super` function. A reference to ``d.parents`` is equivalent to: ``ChainMap(*d.maps[1:])``. - .. versionadded:: 3.3 - Example of simulating Python's internal lookup chain:: import builtins diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -804,7 +804,7 @@ to receive a SIGPIPE if p2 exits before p1. Alternatively, for trusted input, the shell's own pipeline support may still -be used directly: +be used directly:: output=`dmesg | grep hda` # becomes diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -174,7 +174,7 @@ *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 - unsupported, a :exc:`ThreadError` is raised. If the specified 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. 32kB is currently the minimum supported stack size value to guarantee sufficient stack space for the interpreter itself. Note that some platforms may have @@ -452,7 +452,7 @@ are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed. - Do not call this method when the lock is unlocked. + When invoked on an unlocked lock, a :exc:`RuntimeError` is raised. There is no return value. diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -486,6 +486,8 @@ (:issue:`10516`) +.. XXX mention new error messages for passing wrong number of arguments to functions + New and Improved Modules ======================== @@ -572,6 +574,26 @@ The ``unicode_internal`` codec has been deprecated. + +collections +----------- + +Addition of a new :class:`~collections.ChainMap` class to allow treating a +number of mappings as a single unit. + +(Written by Raymond Hettinger for :issue:`11089`, made public in +:issue:`11297`) + +The abstract base classes have been moved in a new :mod:`collections.abc` +module, to better differentiate between the abstract and the concrete +collections classes. Aliases for ABCs are still present in the +:mod:`collections` module to preserve existing imports. + +(:issue:`11085`) + +.. XXX addition of __slots__ to ABCs not recorded here: internal detail + + crypt ----- @@ -865,11 +887,12 @@ --------- :mod:`distutils` has undergone additions and refactoring under a new name, -:mod:`packaging`, to allow developers to break backward compatibility. +:mod:`packaging`, to allow developers to make far-reaching changes without +being constrained by backward compatibility. :mod:`distutils` is still provided in the standard library, but users are encouraged to transition to :mod:`packaging`. For older versions of Python, a -backport compatible with 2.4+ and 3.1+ will be made available on PyPI under the -name :mod:`distutils2`. +backport compatible with Python 2.5 and newer and 3.2 is available on PyPI +under the name `distutils2 `_. .. TODO add examples and howto to the packaging docs and link to them @@ -1057,12 +1080,24 @@ (:issue:`1673007`) +webbrowser +---------- + +The :mod:`webbrowser` module supports more browsers: Google Chrome (named +:program:`chrome`, :program:`chromium`, :program:`chrome-browser` or +:program:`chromium-browser` depending on the version and operating system) as +well as the the generic launchers :program:`xdg-open` from the FreeDesktop.org +project and :program:`gvfs-open` which is the default URI handler for GNOME 3. + +(:issue:`13620` and :issue:`14493`) + + Optimizations ============= Major performance enhancements have been added: -* Thanks to the :pep:`393`, some operations on Unicode strings has been optimized: +* Thanks to :pep:`393`, some operations on Unicode strings have been optimized: * the memory footprint is divided by 2 to 4 depending on the text * encode an ASCII string to UTF-8 doesn't need to encode characters anymore, @@ -1081,7 +1116,7 @@ * :c:func:`PyMemoryView_FromMemory` -* The :pep:`393` added new Unicode types, macros and functions: +* :pep:`393` added new Unicode types, macros and functions: * High-level API: @@ -1124,7 +1159,7 @@ Deprecated Python modules, functions and methods ------------------------------------------------ -* The :mod:`distutils` modules has been deprecated. Use the new +* The :mod:`distutils` module has been deprecated. Use the new :mod:`packaging` module instead. * The ``unicode_internal`` codec has been deprecated because of the :pep:`393`, use UTF-8, UTF-16 (``utf-16-le`` or ``utf-16-be``), or UTF-32 @@ -1143,7 +1178,7 @@ Deprecated functions and types of the C API ------------------------------------------- -The :c:type:`Py_UNICODE` has been deprecated by the :pep:`393` and will be +The :c:type:`Py_UNICODE` has been deprecated by :pep:`393` and will be removed in Python 4. All functions using this type are deprecated: Unicode functions and methods using :c:type:`Py_UNICODE` and @@ -1245,7 +1280,7 @@ functions using this type are deprecated (but will stay available for at least five years). If you were using low-level Unicode APIs to construct and access unicode objects and you want to benefit of the - memory footprint reduction provided by the PEP 393, you have to convert + memory footprint reduction provided by PEP 393, you have to convert your code to the new :doc:`Unicode API <../c-api/unicode>`. However, if you only have been using high-level functions such as diff --git a/Include/methodobject.h b/Include/methodobject.h --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -17,7 +17,7 @@ typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *, - PyObject *); + PyObject *); typedef PyObject *(*PyNoArgsFunction)(PyObject *); PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *); @@ -33,22 +33,22 @@ (((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_STATIC ? \ NULL : ((PyCFunctionObject *)func) -> m_self) #define PyCFunction_GET_FLAGS(func) \ - (((PyCFunctionObject *)func) -> m_ml -> ml_flags) + (((PyCFunctionObject *)func) -> m_ml -> ml_flags) #endif PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); struct PyMethodDef { - const char *ml_name; /* The name of the built-in function/method */ - PyCFunction ml_meth; /* The C function that implements it */ - int ml_flags; /* Combination of METH_xxx flags, which mostly - describe the args expected by the C func */ - const char *ml_doc; /* The __doc__ attribute, or NULL */ + const char *ml_name; /* The name of the built-in function/method */ + PyCFunction ml_meth; /* The C function that implements it */ + int ml_flags; /* Combination of METH_xxx flags, which mostly + describe the args expected by the C func */ + const char *ml_doc; /* The __doc__ attribute, or NULL */ }; typedef struct PyMethodDef PyMethodDef; #define PyCFunction_New(ML, SELF) PyCFunction_NewEx((ML), (SELF), NULL) PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *, - PyObject *); + PyObject *); /* Flag passed to newmethodobject */ /* #define METH_OLDARGS 0x0000 -- unsupported now */ diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -535,6 +535,11 @@ _PyObject_GenericSetAttrWithDict(PyObject *, PyObject *, PyObject *, PyObject *); +/* Helper to look up a builtin object */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) +_PyObject_GetBuiltin(const char *name); +#endif /* PyObject_Dir(obj) acts like Python builtins.dir(obj), returning a list of strings. PyObject_Dir(NULL) is like builtins.dir(), diff --git a/Lib/collections/abc.py b/Lib/collections/abc.py --- a/Lib/collections/abc.py +++ b/Lib/collections/abc.py @@ -18,9 +18,13 @@ "ByteString", ] - -### collection related types which are not exposed through builtin ### -## iterators ## +# Private list of types that we want to register with the various ABCs +# so that they will pass tests like: +# it = iter(somebytearray) +# assert isinstance(it, Iterable) +# Note: in other implementations, these types many not be distinct +# and they make have their own implementation specific types that +# are not included on this list. bytes_iterator = type(iter(b'')) bytearray_iterator = type(iter(bytearray())) #callable_iterator = ??? diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,6 +1,9 @@ What's New in IDLE 3.3? ========================= +- Issue #8515: Set __file__ when run file in IDLE. + Initial patch by Bruce Frederiksen. + - IDLE can be launched as `python -m idlelib` - Issue #14409: IDLE now properly executes commands in the Shell window diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -150,16 +150,16 @@ dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: - _filename = %r + __file__ = {filename!r} import sys as _sys from os.path import basename as _basename if (not _sys.argv or - _basename(_sys.argv[0]) != _basename(_filename)): - _sys.argv = [_filename] + _basename(_sys.argv[0]) != _basename(__file__)): + _sys.argv = [__file__] import os as _os - _os.chdir(%r) - del _filename, _sys, _basename, _os - \n""" % (filename, dirname)) + _os.chdir({dirname!r}) + del _sys, _basename, _os + \n""".format(filename=filename, dirname=dirname)) interp.prepend_syspath(filename) # XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still # go to __stderr__. With subprocess, they go to the shell. diff --git a/Lib/idlelib/tabbedpages.py b/Lib/idlelib/tabbedpages.py --- a/Lib/idlelib/tabbedpages.py +++ b/Lib/idlelib/tabbedpages.py @@ -78,7 +78,7 @@ def remove_tab(self, tab_name): """Remove the tab named """ if not tab_name in self._tab_names: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) self._tab_names.remove(tab_name) self._arrange_tabs() @@ -88,7 +88,7 @@ if tab_name == self._selected_tab: return if tab_name is not None and tab_name not in self._tabs: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) # deselect the current selected tab if self._selected_tab is not None: diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -111,6 +111,10 @@ if sys.platform != 'win32' and family == 'AF_PIPE': raise ValueError('Family %s is not recognized.' % family) + if sys.platform == 'win32' and family == 'AF_UNIX': + # double check + if not hasattr(socket, family): + raise ValueError('Family %s is not recognized.' % family) def address_type(address): ''' diff --git a/Lib/test/seq_tests.py b/Lib/test/seq_tests.py --- a/Lib/test/seq_tests.py +++ b/Lib/test/seq_tests.py @@ -4,6 +4,7 @@ import unittest import sys +import pickle # Various iterables # This is used for checking the constructor (here and in test_deque.py) @@ -388,3 +389,9 @@ self.assertEqual(a.index(0, -4*sys.maxsize, 4*sys.maxsize), 2) self.assertRaises(ValueError, a.index, 0, 4*sys.maxsize,-4*sys.maxsize) self.assertRaises(ValueError, a.index, 2, 0, -10) + + def test_pickle(self): + lst = self.type2test([4, 5, 6, 7]) + lst2 = pickle.loads(pickle.dumps(lst)) + self.assertEqual(lst2, lst) + self.assertNotEqual(id(lst2), id(lst)) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -285,6 +285,20 @@ self.assertEqual(a.x, b.x) self.assertEqual(type(a), type(b)) + def test_iterator_pickle(self): + data = array.array(self.typecode, self.example) + orgit = iter(data) + d = pickle.dumps(orgit) + it = pickle.loads(d) + self.assertEqual(type(orgit), type(it)) + self.assertEqual(list(it), list(data)) + + if len(data): + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(list(it), list(data)[1:]) + def test_insert(self): a = array.array(self.typecode, self.example) a.insert(0, self.example[0]) diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -74,15 +74,16 @@ pass else: n = 200 - while n > 0: - r, w, e = select.select([conn], [], []) + start = time.time() + while n > 0 and time.time() - start < 3.0: + r, w, e = select.select([conn], [], [], 0.1) if r: + n -= 1 data = conn.recv(10) # keep everything except for the newline terminator buf.write(data.replace(b'\n', b'')) if b'\n' in data: break - n -= 1 time.sleep(0.01) conn.close() diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -14,6 +14,7 @@ import traceback from test.support import TESTFN, unlink, run_unittest, check_warnings from operator import neg +import pickle try: import pty, signal except ImportError: @@ -110,7 +111,30 @@ def __iter__(self): raise RuntimeError +def filter_char(arg): + return ord(arg) > ord("d") + +def map_char(arg): + return chr(ord(arg)+1) + class BuiltinTest(unittest.TestCase): + # Helper to check picklability + def check_iter_pickle(self, it, seq): + itorg = it + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), seq) + + #test the iterator after dropping one from it + it = pickle.loads(d) + try: + next(it) + except StopIteration: + return + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), seq[1:]) def test_import(self): __import__('sys') @@ -566,6 +590,11 @@ self.assertEqual(list(filter(lambda x: x>=3, (1, 2, 3, 4))), [3, 4]) self.assertRaises(TypeError, list, filter(42, (1, 2))) + def test_filter_pickle(self): + f1 = filter(filter_char, "abcdeabcde") + f2 = filter(filter_char, "abcdeabcde") + self.check_iter_pickle(f1, list(f2)) + def test_getattr(self): self.assertTrue(getattr(sys, 'stdout') is sys.stdout) self.assertRaises(TypeError, getattr, sys, 1) @@ -759,6 +788,11 @@ raise RuntimeError self.assertRaises(RuntimeError, list, map(badfunc, range(5))) + def test_map_pickle(self): + m1 = map(map_char, "Is this the real life?") + m2 = map(map_char, "Is this the real life?") + self.check_iter_pickle(m1, list(m2)) + def test_max(self): self.assertEqual(max('123123'), '3') self.assertEqual(max(1, 2, 3), 3) @@ -1300,6 +1334,13 @@ return i self.assertRaises(ValueError, list, zip(BadSeq(), BadSeq())) + def test_zip_pickle(self): + a = (1, 2, 3) + b = (4, 5, 6) + t = [(1, 4), (2, 5), (3, 6)] + z1 = zip(a, b) + self.check_iter_pickle(z1, t) + def test_format(self): # Test the basic machinery of the format() builtin. Don't test # the specifics of the various formatters diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -518,6 +518,24 @@ q = pickle.loads(ps) self.assertEqual(b, q) + def test_iterator_pickling(self): + for b in b"", b"a", b"abc", b"\xffab\x80", b"\0\0\377\0\0": + it = itorg = iter(self.type2test(b)) + data = list(self.type2test(b)) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), data) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + continue + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), data[1:]) + def test_strip(self): b = self.type2test(b'mississippi') self.assertEqual(b.strip(b'i'), b'mississipp') diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -4953,6 +4953,78 @@ self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g') self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g') + def test_exact_conversion(self): + Decimal = C.Decimal + localcontext = C.localcontext + InvalidOperation = C.InvalidOperation + + with localcontext() as c: + + c.traps[InvalidOperation] = True + + # Clamped + x = "0e%d" % sys.maxsize + self.assertRaises(InvalidOperation, Decimal, x) + + x = "0e%d" % (-sys.maxsize-1) + self.assertRaises(InvalidOperation, Decimal, x) + + # Overflow + x = "1e%d" % sys.maxsize + self.assertRaises(InvalidOperation, Decimal, x) + + # Underflow + x = "1e%d" % (-sys.maxsize-1) + self.assertRaises(InvalidOperation, Decimal, x) + + def test_from_tuple(self): + Decimal = C.Decimal + localcontext = C.localcontext + InvalidOperation = C.InvalidOperation + Overflow = C.Overflow + Underflow = C.Underflow + + with localcontext() as c: + + c.traps[InvalidOperation] = True + c.traps[Overflow] = True + c.traps[Underflow] = True + + # SSIZE_MAX + x = (1, (), sys.maxsize) + self.assertEqual(str(c.create_decimal(x)), '-0E+999999') + self.assertRaises(InvalidOperation, Decimal, x) + + x = (1, (0, 1, 2), sys.maxsize) + self.assertRaises(Overflow, c.create_decimal, x) + self.assertRaises(InvalidOperation, Decimal, x) + + # SSIZE_MIN + x = (1, (), -sys.maxsize-1) + self.assertEqual(str(c.create_decimal(x)), '-0E-1000026') + self.assertRaises(InvalidOperation, Decimal, x) + + x = (1, (0, 1, 2), -sys.maxsize-1) + self.assertRaises(Underflow, c.create_decimal, x) + self.assertRaises(InvalidOperation, Decimal, x) + + # OverflowError + x = (1, (), sys.maxsize+1) + self.assertRaises(OverflowError, c.create_decimal, x) + self.assertRaises(OverflowError, Decimal, x) + + x = (1, (), -sys.maxsize-2) + self.assertRaises(OverflowError, c.create_decimal, x) + self.assertRaises(OverflowError, Decimal, x) + + # Specials + x = (1, (), "N") + self.assertEqual(str(Decimal(x)), '-sNaN') + x = (1, (0,), "N") + self.assertEqual(str(Decimal(x)), '-sNaN') + x = (1, (0, 1), "N") + self.assertEqual(str(Decimal(x)), '-sNaN1') + all_tests = [ CExplicitConstructionTest, PyExplicitConstructionTest, 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 @@ -471,6 +471,19 @@ ## self.assertNotEqual(id(d), id(e)) ## self.assertEqual(id(e), id(e[-1])) + def test_iterator_pickle(self): + data = deque(range(200)) + it = itorg = iter(data) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), list(data)) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(list(it), list(data)[1:]) + def test_deepcopy(self): mut = [10] d = deque([mut]) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -2,7 +2,9 @@ from test import support import collections, random, string +import collections.abc import gc, weakref +import pickle class DictTest(unittest.TestCase): @@ -803,6 +805,58 @@ pass self._tracked(MyDict()) + def test_iterator_pickling(self): + data = {1:"a", 2:"b", 3:"c"} + it = iter(data) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(sorted(it), sorted(data)) + + it = pickle.loads(d) + try: + drop = next(it) + except StopIteration: + return + d = pickle.dumps(it) + it = pickle.loads(d) + del data[drop] + self.assertEqual(sorted(it), sorted(data)) + + def test_itemiterator_pickling(self): + data = {1:"a", 2:"b", 3:"c"} + # dictviews aren't picklable, only their iterators + itorg = iter(data.items()) + d = pickle.dumps(itorg) + it = pickle.loads(d) + # note that the type of type of the unpickled iterator + # is not necessarily the same as the original. It is + # merely an object supporting the iterator protocol, yielding + # the same objects as the original one. + # self.assertEqual(type(itorg), type(it)) + self.assertTrue(isinstance(it, collections.abc.Iterator)) + self.assertEqual(dict(it), data) + + it = pickle.loads(d) + drop = next(it) + d = pickle.dumps(it) + it = pickle.loads(d) + del data[drop[0]] + self.assertEqual(dict(it), data) + + def test_valuesiterator_pickling(self): + data = {1:"a", 2:"b", 3:"c"} + # data.values() isn't picklable, only its iterator + it = iter(data.values()) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(sorted(list(it)), sorted(list(data.values()))) + + it = pickle.loads(d) + drop = next(it) + d = pickle.dumps(it) + it = pickle.loads(d) + values = list(it) + [drop] + self.assertEqual(sorted(values), sorted(list(data.values()))) from test import mapping_tests diff --git a/Lib/test/test_enumerate.py b/Lib/test/test_enumerate.py --- a/Lib/test/test_enumerate.py +++ b/Lib/test/test_enumerate.py @@ -1,5 +1,6 @@ import unittest import sys +import pickle from test import support @@ -61,7 +62,25 @@ def __iter__(self): return self -class EnumerateTestCase(unittest.TestCase): +class PickleTest: + # Helper to check picklability + def check_pickle(self, itorg, seq): + d = pickle.dumps(itorg) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), seq) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + self.assertFalse(seq[1:]) + return + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), seq[1:]) + +class EnumerateTestCase(unittest.TestCase, PickleTest): enum = enumerate seq, res = 'abc', [(0,'a'), (1,'b'), (2,'c')] @@ -73,6 +92,9 @@ self.assertEqual(list(self.enum(self.seq)), self.res) self.enum.__doc__ + def test_pickle(self): + self.check_pickle(self.enum(self.seq), self.res) + def test_getitemseqn(self): self.assertEqual(list(self.enum(G(self.seq))), self.res) e = self.enum(G('')) @@ -126,7 +148,7 @@ seq = range(10,20000,2) res = list(zip(range(20000), seq)) -class TestReversed(unittest.TestCase): +class TestReversed(unittest.TestCase, PickleTest): def test_simple(self): class A: @@ -212,6 +234,10 @@ ngi = NoGetItem() self.assertRaises(TypeError, reversed, ngi) + def test_pickle(self): + for data in 'abc', range(5), tuple(enumerate('abc')), range(1,17,5): + self.check_pickle(reversed(data), list(data)[::-1]) + class EnumerateStartTestCase(EnumerateTestCase): diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py --- a/Lib/test/test_iter.py +++ b/Lib/test/test_iter.py @@ -2,6 +2,8 @@ import unittest from test.support import run_unittest, TESTFN, unlink, cpython_only +import pickle +import collections.abc # Test result of triple loop (too big to inline) TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2), @@ -28,6 +30,8 @@ raise StopIteration self.i = res + 1 return res + def __iter__(self): + return self class IteratingSequenceClass: def __init__(self, n): @@ -49,7 +53,9 @@ class TestCase(unittest.TestCase): # Helper to check that an iterator returns a given sequence - def check_iterator(self, it, seq): + def check_iterator(self, it, seq, pickle=True): + if pickle: + self.check_pickle(it, seq) res = [] while 1: try: @@ -60,12 +66,33 @@ self.assertEqual(res, seq) # Helper to check that a for loop generates a given sequence - def check_for_loop(self, expr, seq): + def check_for_loop(self, expr, seq, pickle=True): + if pickle: + self.check_pickle(iter(expr), seq) res = [] for val in expr: res.append(val) self.assertEqual(res, seq) + # Helper to check picklability + def check_pickle(self, itorg, seq): + d = pickle.dumps(itorg) + it = pickle.loads(d) + # Cannot assert type equality because dict iterators unpickle as list + # iterators. + # self.assertEqual(type(itorg), type(it)) + self.assertTrue(isinstance(it, collections.abc.Iterator)) + self.assertEqual(list(it), seq) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + return + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), seq[1:]) + # Test basic use of iter() function def test_iter_basic(self): self.check_iterator(iter(range(10)), list(range(10))) @@ -138,7 +165,7 @@ if i > 100: raise IndexError # Emergency stop return i - self.check_iterator(iter(C(), 10), list(range(10))) + self.check_iterator(iter(C(), 10), list(range(10)), pickle=False) # Test two-argument iter() with function def test_iter_function(self): @@ -146,7 +173,7 @@ i = state[0] state[0] = i+1 return i - self.check_iterator(iter(spam, 10), list(range(10))) + self.check_iterator(iter(spam, 10), list(range(10)), pickle=False) # Test two-argument iter() with function that raises StopIteration def test_iter_function_stop(self): @@ -156,7 +183,7 @@ raise StopIteration state[0] = i+1 return i - self.check_iterator(iter(spam, 20), list(range(10))) + self.check_iterator(iter(spam, 20), list(range(10)), pickle=False) # Test exception propagation through function iterator def test_exception_function(self): @@ -198,7 +225,7 @@ if i == 10: raise StopIteration return SequenceClass.__getitem__(self, i) - self.check_for_loop(MySequenceClass(20), list(range(10))) + self.check_for_loop(MySequenceClass(20), list(range(10)), pickle=False) # Test a big range def test_iter_big_range(self): @@ -237,8 +264,8 @@ f.close() f = open(TESTFN, "r") try: - self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"]) - self.check_for_loop(f, []) + self.check_for_loop(f, ["0\n", "1\n", "2\n", "3\n", "4\n"], pickle=False) + self.check_for_loop(f, [], pickle=False) finally: f.close() try: 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 @@ -37,6 +37,13 @@ 'Test predicate' return x%2==1 +def tupleize(*args): + return args + +def irange(n): + for i in range(n): + yield i + class StopNow: 'Class emulating an empty iterable.' def __iter__(self): @@ -55,8 +62,59 @@ 'Factorial' return prod(range(1, n+1)) +# root level methods for pickling ability +def testR(r): + return r[0] + +def testR2(r): + return r[2] + +def underten(x): + return x<10 + class TestBasicOps(unittest.TestCase): + def pickletest(self, it, stop=4, take=1, compare=None): + """Test that an iterator is the same after pickling, also when part-consumed""" + def expand(it, i=0): + # Recursively expand iterables, within sensible bounds + if i > 10: + raise RuntimeError("infinite recursion encountered") + if isinstance(it, str): + return it + try: + l = list(islice(it, stop)) + except TypeError: + return it # can't expand it + return [expand(e, i+1) for e in l] + + # Test the initial copy against the original + dump = pickle.dumps(it) + i2 = pickle.loads(dump) + self.assertEqual(type(it), type(i2)) + a, b = expand(it), expand(i2) + self.assertEqual(a, b) + if compare: + c = expand(compare) + self.assertEqual(a, c) + + # Take from the copy, and create another copy and compare them. + i3 = pickle.loads(dump) + took = 0 + try: + for i in range(take): + next(i3) + took += 1 + except StopIteration: + pass #in case there is less data than 'take' + dump = pickle.dumps(i3) + i4 = pickle.loads(dump) + a, b = expand(i3), expand(i4) + self.assertEqual(a, b) + if compare: + c = expand(compare[took:]) + self.assertEqual(a, c); + def test_accumulate(self): self.assertEqual(list(accumulate(range(10))), # one positional arg [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]) @@ -83,6 +141,7 @@ [2, 16, 144, 720, 5040, 0, 0, 0, 0, 0]) with self.assertRaises(TypeError): list(accumulate(s, chr)) # unary-operation + self.pickletest(accumulate(range(10))) # test pickling def test_chain(self): @@ -106,14 +165,43 @@ self.assertEqual(take(4, chain.from_iterable(['abc', 'def'])), list('abcd')) self.assertRaises(TypeError, list, chain.from_iterable([2, 3])) + def test_chain_reducible(self): + operators = [copy.deepcopy, + lambda s: pickle.loads(pickle.dumps(s))] + for oper in operators: + it = chain('abc', 'def') + self.assertEqual(list(oper(it)), list('abcdef')) + self.assertEqual(next(it), 'a') + self.assertEqual(list(oper(it)), list('bcdef')) + + self.assertEqual(list(oper(chain(''))), []) + self.assertEqual(take(4, oper(chain('abc', 'def'))), list('abcd')) + self.assertRaises(TypeError, list, oper(chain(2, 3))) + self.pickletest(chain('abc', 'def'), compare=list('abcdef')) + def test_combinations(self): self.assertRaises(TypeError, combinations, 'abc') # missing r argument self.assertRaises(TypeError, combinations, 'abc', 2, 1) # too many arguments self.assertRaises(TypeError, combinations, None) # pool is not iterable self.assertRaises(ValueError, combinations, 'abc', -2) # r is negative - self.assertEqual(list(combinations('abc', 32)), []) # r > n - self.assertEqual(list(combinations(range(4), 3)), - [(0,1,2), (0,1,3), (0,2,3), (1,2,3)]) + + for op in (lambda a:a, lambda a:pickle.loads(pickle.dumps(a))): + self.assertEqual(list(op(combinations('abc', 32))), []) # r > n + + self.assertEqual(list(op(combinations('ABCD', 2))), + [('A','B'), ('A','C'), ('A','D'), ('B','C'), ('B','D'), ('C','D')]) + testIntermediate = combinations('ABCD', 2) + next(testIntermediate) + self.assertEqual(list(op(testIntermediate)), + [('A','C'), ('A','D'), ('B','C'), ('B','D'), ('C','D')]) + + self.assertEqual(list(op(combinations(range(4), 3))), + [(0,1,2), (0,1,3), (0,2,3), (1,2,3)]) + testIntermediate = combinations(range(4), 3) + next(testIntermediate) + self.assertEqual(list(op(testIntermediate)), + [(0,1,3), (0,2,3), (1,2,3)]) + def combinations1(iterable, r): 'Pure python version shown in the docs' @@ -168,6 +256,9 @@ self.assertEqual(result, list(combinations2(values, r))) # matches second pure python version self.assertEqual(result, list(combinations3(values, r))) # matches second pure python version + self.pickletest(combinations(values, r)) # test pickling + + # Test implementation detail: tuple re-use @support.impl_detail("tuple reuse is specific to CPython") def test_combinations_tuple_reuse(self): self.assertEqual(len(set(map(id, combinations('abcde', 3)))), 1) @@ -179,8 +270,15 @@ self.assertRaises(TypeError, cwr, 'abc', 2, 1) # too many arguments self.assertRaises(TypeError, cwr, None) # pool is not iterable self.assertRaises(ValueError, cwr, 'abc', -2) # r is negative - self.assertEqual(list(cwr('ABC', 2)), - [('A','A'), ('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')]) + + for op in (lambda a:a, lambda a:pickle.loads(pickle.dumps(a))): + self.assertEqual(list(op(cwr('ABC', 2))), + [('A','A'), ('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')]) + testIntermediate = cwr('ABC', 2) + next(testIntermediate) + self.assertEqual(list(op(testIntermediate)), + [('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')]) + def cwr1(iterable, r): 'Pure python version shown in the docs' @@ -239,6 +337,10 @@ self.assertEqual(result, list(cwr1(values, r))) # matches first pure python version self.assertEqual(result, list(cwr2(values, r))) # matches second pure python version + self.pickletest(cwr(values,r)) # test pickling + + # Test implementation detail: tuple re-use + @support.impl_detail("tuple reuse is specific to CPython") def test_combinations_with_replacement_tuple_reuse(self): cwr = combinations_with_replacement @@ -305,6 +407,8 @@ self.assertEqual(result, list(permutations(values, None))) # test r as None self.assertEqual(result, list(permutations(values))) # test default r + self.pickletest(permutations(values, r)) # test pickling + @support.impl_detail("tuple resuse is CPython specific") def test_permutations_tuple_reuse(self): self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1) @@ -359,6 +463,24 @@ self.assertRaises(TypeError, compress, range(6)) # too few args self.assertRaises(TypeError, compress, range(6), None) # too many args + # check copy, deepcopy, pickle + for op in (lambda a:copy.copy(a), lambda a:copy.deepcopy(a), lambda a:pickle.loads(pickle.dumps(a))): + for data, selectors, result1, result2 in [ + ('ABCDEF', [1,0,1,0,1,1], 'ACEF', 'CEF'), + ('ABCDEF', [0,0,0,0,0,0], '', ''), + ('ABCDEF', [1,1,1,1,1,1], 'ABCDEF', 'BCDEF'), + ('ABCDEF', [1,0,1], 'AC', 'C'), + ('ABC', [0,1,1,1,1,1], 'BC', 'C'), + ]: + + self.assertEqual(list(op(compress(data=data, selectors=selectors))), list(result1)) + self.assertEqual(list(op(compress(data, selectors))), list(result1)) + testIntermediate = compress(data, selectors) + if result1: + next(testIntermediate) + self.assertEqual(list(op(testIntermediate)), list(result2)) + + def test_count(self): self.assertEqual(lzip('abc',count()), [('a', 0), ('b', 1), ('c', 2)]) self.assertEqual(lzip('abc',count(3)), [('a', 3), ('b', 4), ('c', 5)]) @@ -393,7 +515,7 @@ c = count(value) self.assertEqual(next(copy.copy(c)), value) self.assertEqual(next(copy.deepcopy(c)), value) - self.assertEqual(next(pickle.loads(pickle.dumps(c))), value) + self.pickletest(count(value)) #check proper internal error handling for large "step' sizes count(1, maxsize+5); sys.exc_info() @@ -440,6 +562,7 @@ else: r2 = ('count(%r, %r)' % (i, j)).replace('L', '') self.assertEqual(r1, r2) + self.pickletest(count(i, j)) def test_cycle(self): self.assertEqual(take(10, cycle('abc')), list('abcabcabca')) @@ -448,6 +571,18 @@ self.assertRaises(TypeError, cycle, 5) self.assertEqual(list(islice(cycle(gen3()),10)), [0,1,2,0,1,2,0,1,2,0]) + # check copy, deepcopy, pickle + c = cycle('abc') + self.assertEqual(next(c), 'a') + #simple copy currently not supported, because __reduce__ returns + #an internal iterator + #self.assertEqual(take(10, copy.copy(c)), list('bcabcabcab')) + self.assertEqual(take(10, copy.deepcopy(c)), list('bcabcabcab')) + self.assertEqual(take(10, pickle.loads(pickle.dumps(c))), list('bcabcabcab')) + next(c) + self.assertEqual(take(10, pickle.loads(pickle.dumps(c))), list('cabcabcabc')) + self.pickletest(cycle('abc')) + def test_groupby(self): # Check whether it accepts arguments correctly self.assertEqual([], list(groupby([]))) @@ -466,18 +601,37 @@ dup.append(elem) self.assertEqual(s, dup) + # Check normal pickled + dup = [] + for k, g in pickle.loads(pickle.dumps(groupby(s, testR))): + for elem in g: + self.assertEqual(k, elem[0]) + dup.append(elem) + self.assertEqual(s, dup) + # Check nested case dup = [] - for k, g in groupby(s, lambda r:r[0]): - for ik, ig in groupby(g, lambda r:r[2]): + for k, g in groupby(s, testR): + for ik, ig in groupby(g, testR2): for elem in ig: self.assertEqual(k, elem[0]) self.assertEqual(ik, elem[2]) dup.append(elem) self.assertEqual(s, dup) + # Check nested and pickled + dup = [] + for k, g in pickle.loads(pickle.dumps(groupby(s, testR))): + for ik, ig in pickle.loads(pickle.dumps(groupby(g, testR2))): + for elem in ig: + self.assertEqual(k, elem[0]) + self.assertEqual(ik, elem[2]) + dup.append(elem) + self.assertEqual(s, dup) + + # Check case where inner iterator is not used - keys = [k for k, g in groupby(s, lambda r:r[0])] + keys = [k for k, g in groupby(s, testR)] expectedkeys = set([r[0] for r in s]) self.assertEqual(set(keys), expectedkeys) self.assertEqual(len(keys), len(expectedkeys)) @@ -548,6 +702,20 @@ self.assertRaises(TypeError, filter, isEven, 3) self.assertRaises(TypeError, next, filter(range(6), range(6))) + # check copy, deepcopy, pickle + ans = [0,2,4] + + c = filter(isEven, range(6)) + self.assertEqual(list(copy.copy(c)), ans) + c = filter(isEven, range(6)) + self.assertEqual(list(copy.deepcopy(c)), ans) + c = filter(isEven, range(6)) + self.assertEqual(list(pickle.loads(pickle.dumps(c))), ans) + next(c) + self.assertEqual(list(pickle.loads(pickle.dumps(c))), ans[1:]) + c = filter(isEven, range(6)) + self.pickletest(c) + def test_filterfalse(self): self.assertEqual(list(filterfalse(isEven, range(6))), [1,3,5]) self.assertEqual(list(filterfalse(None, [0,1,0,2,0])), [0,0,0]) @@ -558,6 +726,7 @@ self.assertRaises(TypeError, filterfalse, lambda x:x, range(6), 7) self.assertRaises(TypeError, filterfalse, isEven, 3) self.assertRaises(TypeError, next, filterfalse(range(6), range(6))) + self.pickletest(filterfalse(isEven, range(6))) def test_zip(self): # XXX This is rather silly now that builtin zip() calls zip()... @@ -582,6 +751,23 @@ ids = list(map(id, list(zip('abc', 'def')))) self.assertEqual(len(dict.fromkeys(ids)), len(ids)) + # check copy, deepcopy, pickle + ans = [(x,y) for x, y in copy.copy(zip('abc',count()))] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + + ans = [(x,y) for x, y in copy.deepcopy(zip('abc',count()))] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + + ans = [(x,y) for x, y in pickle.loads(pickle.dumps(zip('abc',count())))] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + + testIntermediate = zip('abc',count()) + next(testIntermediate) + ans = [(x,y) for x, y in pickle.loads(pickle.dumps(testIntermediate))] + self.assertEqual(ans, [('b', 1), ('c', 2)]) + + self.pickletest(zip('abc', count())) + def test_ziplongest(self): for args in [ ['abc', range(6)], @@ -631,6 +817,12 @@ ids = list(map(id, list(zip_longest('abc', 'def')))) self.assertEqual(len(dict.fromkeys(ids)), len(ids)) + def test_zip_longest_pickling(self): + self.pickletest(zip_longest("abc", "def")) + self.pickletest(zip_longest("abc", "defgh")) + self.pickletest(zip_longest("abc", "defgh", fillvalue=1)) + self.pickletest(zip_longest("", "defgh")) + def test_bug_7244(self): class Repeater: @@ -734,6 +926,20 @@ self.assertEqual(len(set(map(id, product('abc', 'def')))), 1) self.assertNotEqual(len(set(map(id, list(product('abc', 'def'))))), 1) + def test_product_pickling(self): + # check copy, deepcopy, pickle + for args, result in [ + ([], [()]), # zero iterables + (['ab'], [('a',), ('b',)]), # one iterable + ([range(2), range(3)], [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2)]), # two iterables + ([range(0), range(2), range(3)], []), # first iterable with zero length + ([range(2), range(0), range(3)], []), # middle iterable with zero length + ([range(2), range(3), range(0)], []), # last iterable with zero length + ]: + self.assertEqual(list(copy.copy(product(*args))), result) + self.assertEqual(list(copy.deepcopy(product(*args))), result) + self.pickletest(product(*args)) + def test_repeat(self): self.assertEqual(list(repeat(object='a', times=3)), ['a', 'a', 'a']) self.assertEqual(lzip(range(3),repeat('a')), @@ -752,11 +958,16 @@ list(r) self.assertEqual(repr(r), 'repeat((1+0j), 0)') + # check copy, deepcopy, pickle + c = repeat(object='a', times=10) + self.assertEqual(next(c), 'a') + self.assertEqual(take(2, copy.copy(c)), list('a' * 2)) + self.assertEqual(take(2, copy.deepcopy(c)), list('a' * 2)) + self.pickletest(repeat(object='a', times=10)) + def test_map(self): self.assertEqual(list(map(operator.pow, range(3), range(1,7))), [0**1, 1**2, 2**3]) - def tupleize(*args): - return args self.assertEqual(list(map(tupleize, 'abc', range(5))), [('a',0),('b',1),('c',2)]) self.assertEqual(list(map(tupleize, 'abc', count())), @@ -771,6 +982,18 @@ self.assertRaises(ValueError, next, map(errfunc, [4], [5])) self.assertRaises(TypeError, next, map(onearg, [4], [5])) + # check copy, deepcopy, pickle + ans = [('a',0),('b',1),('c',2)] + + c = map(tupleize, 'abc', count()) + self.assertEqual(list(copy.copy(c)), ans) + + c = map(tupleize, 'abc', count()) + self.assertEqual(list(copy.deepcopy(c)), ans) + + c = map(tupleize, 'abc', count()) + self.pickletest(c) + def test_starmap(self): self.assertEqual(list(starmap(operator.pow, zip(range(3), range(1,7)))), [0**1, 1**2, 2**3]) @@ -785,6 +1008,18 @@ self.assertRaises(ValueError, next, starmap(errfunc, [(4,5)])) self.assertRaises(TypeError, next, starmap(onearg, [(4,5)])) + # check copy, deepcopy, pickle + ans = [0**1, 1**2, 2**3] + + c = starmap(operator.pow, zip(range(3), range(1,7))) + self.assertEqual(list(copy.copy(c)), ans) + + c = starmap(operator.pow, zip(range(3), range(1,7))) + self.assertEqual(list(copy.deepcopy(c)), ans) + + c = starmap(operator.pow, zip(range(3), range(1,7))) + self.pickletest(c) + def test_islice(self): for args in [ # islice(args) should agree with range(args) (10, 20, 3), @@ -817,17 +1052,18 @@ self.assertEqual(list(it), list(range(3, 10))) # Test invalid arguments - self.assertRaises(TypeError, islice, range(10)) - self.assertRaises(TypeError, islice, range(10), 1, 2, 3, 4) - self.assertRaises(ValueError, islice, range(10), -5, 10, 1) - self.assertRaises(ValueError, islice, range(10), 1, -5, -1) - self.assertRaises(ValueError, islice, range(10), 1, 10, -1) - self.assertRaises(ValueError, islice, range(10), 1, 10, 0) - self.assertRaises(ValueError, islice, range(10), 'a') - self.assertRaises(ValueError, islice, range(10), 'a', 1) - self.assertRaises(ValueError, islice, range(10), 1, 'a') - self.assertRaises(ValueError, islice, range(10), 'a', 1, 1) - self.assertRaises(ValueError, islice, range(10), 1, 'a', 1) + ra = range(10) + self.assertRaises(TypeError, islice, ra) + self.assertRaises(TypeError, islice, ra, 1, 2, 3, 4) + self.assertRaises(ValueError, islice, ra, -5, 10, 1) + self.assertRaises(ValueError, islice, ra, 1, -5, -1) + self.assertRaises(ValueError, islice, ra, 1, 10, -1) + self.assertRaises(ValueError, islice, ra, 1, 10, 0) + self.assertRaises(ValueError, islice, ra, 'a') + self.assertRaises(ValueError, islice, ra, 'a', 1) + self.assertRaises(ValueError, islice, ra, 1, 'a') + self.assertRaises(ValueError, islice, ra, 'a', 1, 1) + self.assertRaises(ValueError, islice, ra, 1, 'a', 1) self.assertEqual(len(list(islice(count(), 1, 10, maxsize))), 1) # Issue #10323: Less islice in a predictable state @@ -835,9 +1071,22 @@ self.assertEqual(list(islice(c, 1, 3, 50)), [1]) self.assertEqual(next(c), 3) + # check copy, deepcopy, pickle + for args in [ # islice(args) should agree with range(args) + (10, 20, 3), + (10, 3, 20), + (10, 20), + (10, 3), + (20,) + ]: + self.assertEqual(list(copy.copy(islice(range(100), *args))), + list(range(*args))) + self.assertEqual(list(copy.deepcopy(islice(range(100), *args))), + list(range(*args))) + self.pickletest(islice(range(100), *args)) + def test_takewhile(self): data = [1, 3, 5, 20, 2, 4, 6, 8] - underten = lambda x: x<10 self.assertEqual(list(takewhile(underten, data)), [1, 3, 5]) self.assertEqual(list(takewhile(underten, [])), []) self.assertRaises(TypeError, takewhile) @@ -849,9 +1098,14 @@ self.assertEqual(list(t), [1, 1, 1]) self.assertRaises(StopIteration, next, t) + # check copy, deepcopy, pickle + self.assertEqual(list(copy.copy(takewhile(underten, data))), [1, 3, 5]) + self.assertEqual(list(copy.deepcopy(takewhile(underten, data))), + [1, 3, 5]) + self.pickletest(takewhile(underten, data)) + def test_dropwhile(self): data = [1, 3, 5, 20, 2, 4, 6, 8] - underten = lambda x: x<10 self.assertEqual(list(dropwhile(underten, data)), [20, 2, 4, 6, 8]) self.assertEqual(list(dropwhile(underten, [])), []) self.assertRaises(TypeError, dropwhile) @@ -860,11 +1114,14 @@ self.assertRaises(TypeError, next, dropwhile(10, [(4,5)])) self.assertRaises(ValueError, next, dropwhile(errfunc, [(4,5)])) + # check copy, deepcopy, pickle + self.assertEqual(list(copy.copy(dropwhile(underten, data))), [20, 2, 4, 6, 8]) + self.assertEqual(list(copy.deepcopy(dropwhile(underten, data))), + [20, 2, 4, 6, 8]) + self.pickletest(dropwhile(underten, data)) + def test_tee(self): n = 200 - def irange(n): - for i in range(n): - yield i a, b = tee([]) # test empty iterator self.assertEqual(list(a), []) @@ -949,6 +1206,67 @@ del a self.assertRaises(ReferenceError, getattr, p, '__class__') + ans = list('abc') + long_ans = list(range(10000)) + + # check copy + a, b = tee('abc') + self.assertEqual(list(copy.copy(a)), ans) + self.assertEqual(list(copy.copy(b)), ans) + a, b = tee(list(range(10000))) + self.assertEqual(list(copy.copy(a)), long_ans) + self.assertEqual(list(copy.copy(b)), long_ans) + + # check partially consumed copy + a, b = tee('abc') + take(2, a) + take(1, b) + self.assertEqual(list(copy.copy(a)), ans[2:]) + self.assertEqual(list(copy.copy(b)), ans[1:]) + self.assertEqual(list(a), ans[2:]) + self.assertEqual(list(b), ans[1:]) + a, b = tee(range(10000)) + take(100, a) + take(60, b) + self.assertEqual(list(copy.copy(a)), long_ans[100:]) + self.assertEqual(list(copy.copy(b)), long_ans[60:]) + self.assertEqual(list(a), long_ans[100:]) + self.assertEqual(list(b), long_ans[60:]) + + # check deepcopy + a, b = tee('abc') + self.assertEqual(list(copy.deepcopy(a)), ans) + self.assertEqual(list(copy.deepcopy(b)), ans) + self.assertEqual(list(a), ans) + self.assertEqual(list(b), ans) + a, b = tee(range(10000)) + self.assertEqual(list(copy.deepcopy(a)), long_ans) + self.assertEqual(list(copy.deepcopy(b)), long_ans) + self.assertEqual(list(a), long_ans) + self.assertEqual(list(b), long_ans) + + # check partially consumed deepcopy + a, b = tee('abc') + take(2, a) + take(1, b) + self.assertEqual(list(copy.deepcopy(a)), ans[2:]) + self.assertEqual(list(copy.deepcopy(b)), ans[1:]) + self.assertEqual(list(a), ans[2:]) + self.assertEqual(list(b), ans[1:]) + a, b = tee(range(10000)) + take(100, a) + take(60, b) + self.assertEqual(list(copy.deepcopy(a)), long_ans[100:]) + self.assertEqual(list(copy.deepcopy(b)), long_ans[60:]) + self.assertEqual(list(a), long_ans[100:]) + self.assertEqual(list(b), long_ans[60:]) + + # check pickle + self.pickletest(iter(tee('abc'))) + a, b = tee('abc') + self.pickletest(a, compare=ans) + self.pickletest(b, compare=ans) + def test_StopIteration(self): self.assertRaises(StopIteration, next, zip()) @@ -974,9 +1292,21 @@ class TestExamples(unittest.TestCase): - def test_accumlate(self): + def test_accumulate(self): self.assertEqual(list(accumulate([1,2,3,4,5])), [1, 3, 6, 10, 15]) + def test_accumulate_reducible(self): + # check copy, deepcopy, pickle + data = [1, 2, 3, 4, 5] + accumulated = [1, 3, 6, 10, 15] + it = accumulate(data) + + self.assertEqual(list(pickle.loads(pickle.dumps(it))), accumulated[:]) + self.assertEqual(next(it), 1) + self.assertEqual(list(pickle.loads(pickle.dumps(it))), accumulated[1:]) + self.assertEqual(list(copy.deepcopy(it)), accumulated[1:]) + self.assertEqual(list(copy.copy(it)), accumulated[1:]) + def test_chain(self): self.assertEqual(''.join(chain('ABC', 'DEF')), 'ABCDEF') diff --git a/Lib/test/test_list.py b/Lib/test/test_list.py --- a/Lib/test/test_list.py +++ b/Lib/test/test_list.py @@ -1,5 +1,6 @@ import sys from test import support, list_tests +import pickle class ListTest(list_tests.CommonTest): type2test = list @@ -69,6 +70,33 @@ check(10) # check our checking code check(1000000) + def test_iterator_pickle(self): + # Userlist iterators don't support pickling yet since + # they are based on generators. + data = self.type2test([4, 5, 6, 7]) + it = itorg = iter(data) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(self.type2test(it), self.type2test(data)) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(self.type2test(it), self.type2test(data)[1:]) + + def test_reversed_pickle(self): + data = self.type2test([4, 5, 6, 7]) + it = itorg = reversed(data) + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(self.type2test(it), self.type2test(reversed(data))) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(self.type2test(it), self.type2test(reversed(data))[1:]) def test_main(verbose=None): support.run_unittest(ListTest) diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2649,6 +2649,10 @@ with self.assertRaises(ValueError): multiprocessing.connection.Listener(r'\\.\test') + @unittest.skipUnless(WIN32, "skipped on non-Windows platforms") + def test_invalid_family_win32(self): + with self.assertRaises(ValueError): + multiprocessing.connection.Listener('/var/test.pipe') testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, TestStdinBadfiledescriptor, TestWait, TestInvalidFamily] diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -341,13 +341,35 @@ def test_pickling(self): testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1), - (13, 21, 3), (-2, 2, 2)] + (13, 21, 3), (-2, 2, 2), (2**65, 2**65+2)] for proto in range(pickle.HIGHEST_PROTOCOL + 1): for t in testcases: r = range(*t) self.assertEqual(list(pickle.loads(pickle.dumps(r, proto))), list(r)) + def test_iterator_pickling(self): + testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1), + (13, 21, 3), (-2, 2, 2), (2**65, 2**65+2)] + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + for t in testcases: + it = itorg = iter(range(*t)) + data = list(range(*t)) + + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), data) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + continue + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(list(it), data[1:]) + def test_odd_bug(self): # This used to raise a "SystemError: NULL result without error" # because the range validation step was eating the exception 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 @@ -9,6 +9,7 @@ import sys import warnings import collections +import collections.abc class PassThru(Exception): pass @@ -234,6 +235,26 @@ dup = pickle.loads(p) self.assertEqual(self.s.x, dup.x) + def test_iterator_pickling(self): + itorg = iter(self.s) + data = self.thetype(self.s) + d = pickle.dumps(itorg) + it = pickle.loads(d) + # Set iterators unpickle as list iterators due to the + # undefined order of set items. + # self.assertEqual(type(itorg), type(it)) + self.assertTrue(isinstance(it, collections.abc.Iterator)) + self.assertEqual(self.thetype(it), data) + + it = pickle.loads(d) + try: + drop = next(it) + except StopIteration: + return + d = pickle.dumps(it) + it = pickle.loads(d) + self.assertEqual(self.thetype(it), data - self.thetype((drop,))) + def test_deepcopy(self): class Tracer: def __init__(self, value): diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -5,8 +5,11 @@ """ import os +import sys +import imp import unittest import sysconfig +import tempfile from test import support from test.script_helper import assert_python_ok @@ -17,10 +20,11 @@ srcdir = sysconfig.get_config_var('projectbase') basepath = os.path.join(os.getcwd(), srcdir, 'Tools') +scriptsdir = os.path.join(basepath, 'scripts') class ReindentTests(unittest.TestCase): - script = os.path.join(basepath, 'scripts', 'reindent.py') + script = os.path.join(scriptsdir, 'reindent.py') def test_noargs(self): assert_python_ok(self.script) @@ -31,8 +35,73 @@ self.assertGreater(err, b'') +class TestSundryScripts(unittest.TestCase): + # At least make sure the rest don't have syntax errors. When tests are + # added for a script it should be added to the whitelist below. + + # scripts that have independent tests. + whitelist = ['reindent.py'] + # scripts that can't be imported without running + blacklist = ['make_ctype.py'] + # scripts that use windows-only modules + windows_only = ['win_add2path.py'] + # blacklisted for other reasons + other = ['analyze_dxp.py'] + + skiplist = blacklist + whitelist + windows_only + other + + def setUp(self): + cm = support.DirsOnSysPath(scriptsdir) + cm.__enter__() + self.addCleanup(cm.__exit__) + + def test_sundry(self): + for fn in os.listdir(scriptsdir): + if fn.endswith('.py') and fn not in self.skiplist: + __import__(fn[:-3]) + + @unittest.skipIf(sys.platform != "win32", "Windows-only test") + def test_sundry_windows(self): + for fn in self.windows_only: + __import__(fn[:-3]) + + @unittest.skipIf(not support.threading, "test requires _thread module") + def test_analyze_dxp_import(self): + if hasattr(sys, 'getdxp'): + import analyze_dxp + else: + with self.assertRaises(RuntimeError): + import analyze_dxp + + +class PdepsTests(unittest.TestCase): + + @classmethod + def setUpClass(self): + path = os.path.join(scriptsdir, 'pdeps.py') + self.pdeps = imp.load_source('pdeps', path) + + @classmethod + def tearDownClass(self): + if 'pdeps' in sys.modules: + del sys.modules['pdeps'] + + def test_process_errors(self): + # Issue #14492: m_import.match(line) can be None. + with tempfile.TemporaryDirectory() as tmpdir: + fn = os.path.join(tmpdir, 'foo') + with open(fn, 'w') as stream: + stream.write("#!/this/will/fail") + self.pdeps.process(fn, {}) + + def test_inverse_attribute_error(self): + # Issue #14492: this used to fail with an AttributeError. + self.pdeps.inverse({'a': []}) + + def test_main(): - support.run_unittest(ReindentTests) + support.run_unittest(*[obj for obj in globals().values() + if isinstance(obj, type)]) if __name__ == '__main__': diff --git a/Lib/test/test_tuple.py b/Lib/test/test_tuple.py --- a/Lib/test/test_tuple.py +++ b/Lib/test/test_tuple.py @@ -1,6 +1,7 @@ from test import support, seq_tests import gc +import pickle class TupleTest(seq_tests.CommonTest): type2test = tuple @@ -164,6 +165,34 @@ check(10) # check our checking code check(1000000) + def test_iterator_pickle(self): + # Userlist iterators don't support pickling yet since + # they are based on generators. + data = self.type2test([4, 5, 6, 7]) + itorg = iter(data) + d = pickle.dumps(itorg) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(self.type2test(it), self.type2test(data)) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(self.type2test(it), self.type2test(data)[1:]) + + def test_reversed_pickle(self): + data = self.type2test([4, 5, 6, 7]) + itorg = reversed(data) + d = pickle.dumps(itorg) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(self.type2test(it), self.type2test(reversed(data))) + + it = pickle.loads(d) + next(it) + d = pickle.dumps(it) + self.assertEqual(self.type2test(it), self.type2test(reversed(data))[1:]) + def test_main(): support.run_unittest(TupleTest) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1859,6 +1859,41 @@ gc_collect() self.assertIsNone(wref()) + # A longer cycle: d->e->e2->d + e = ET.Element('joe') + d = Dummy() + d.dummyref = e + wref = weakref.ref(d) + e2 = ET.SubElement(e, 'foo', attr=d) + del d, e, e2 + gc_collect() + self.assertIsNone(wref()) + + # A cycle between Element objects as children of one another + # e1->e2->e3->e1 + e1 = ET.Element('e1') + e2 = ET.Element('e2') + e3 = ET.Element('e3') + e1.append(e2) + e2.append(e2) + e3.append(e1) + wref = weakref.ref(e1) + del e1, e2, e3 + gc_collect() + self.assertIsNone(wref()) + + def test_weakref(self): + flag = False + def wref_cb(w): + nonlocal flag + flag = True + e = ET.Element('e') + wref = weakref.ref(e, wref_cb) + self.assertEqual(wref().tag, 'e') + del e + self.assertEqual(flag, True) + self.assertEqual(wref(), None) + class ElementTreeTest(unittest.TestCase): def test_istype(self): diff --git a/Lib/tkinter/font.py b/Lib/tkinter/font.py --- a/Lib/tkinter/font.py +++ b/Lib/tkinter/font.py @@ -2,27 +2,27 @@ # # written by Fredrik Lundh, February 1998 # -# FIXME: should add 'displayof' option where relevant (actual, families, -# measure, and metrics) -# __version__ = "0.9" +import itertools import tkinter + # weight/slant NORMAL = "normal" ROMAN = "roman" BOLD = "bold" ITALIC = "italic" + def nametofont(name): """Given the name of a tk named font, returns a Font representation. """ return Font(name=name, exists=True) + class Font: - """Represents a named font. Constructor options are: @@ -44,6 +44,8 @@ """ + counter = itertools.count(1) + def _set(self, kw): options = [] for k, v in kw.items(): @@ -63,7 +65,8 @@ options[args[i][1:]] = args[i+1] return options - def __init__(self, root=None, font=None, name=None, exists=False, **options): + def __init__(self, root=None, font=None, name=None, exists=False, + **options): if not root: root = tkinter._default_root if font: @@ -72,7 +75,7 @@ else: font = self._set(options) if not name: - name = "font" + str(id(self)) + name = "font" + str(next(self.counter)) self.name = name if exists: @@ -118,14 +121,17 @@ "Return a distinct copy of the current font" return Font(self._root, **self.actual()) - def actual(self, option=None): + def actual(self, option=None, displayof=None): "Return actual font attributes" + args = () + if displayof: + args = ('-displayof', displayof) if option: - return self._call("font", "actual", self.name, "-"+option) + args = args + ('-' + option, ) + return self._call("font", "actual", self.name, *args) else: return self._mkdict( - self._split(self._call("font", "actual", self.name)) - ) + self._split(self._call("font", "actual", self.name, *args))) def cget(self, option): "Get font attribute" @@ -138,37 +144,47 @@ *self._set(options)) else: return self._mkdict( - self._split(self._call("font", "config", self.name)) - ) + self._split(self._call("font", "config", self.name))) configure = config - def measure(self, text): + def measure(self, text, displayof=None): "Return text width" - return int(self._call("font", "measure", self.name, text)) + args = (text,) + if displayof: + args = ('-displayof', displayof, text) + return int(self._call("font", "measure", self.name, *args)) - def metrics(self, *options): + def metrics(self, *options, **kw): """Return font metrics. For best performance, create a dummy widget using this font before calling this method.""" - + args = () + displayof = kw.pop('displayof', None) + if displayof: + args = ('-displayof', displayof) if options: + args = args + self._get(options) return int( - self._call("font", "metrics", self.name, self._get(options)) - ) + self._call("font", "metrics", self.name, *args)) else: - res = self._split(self._call("font", "metrics", self.name)) + res = self._split(self._call("font", "metrics", self.name, *args)) options = {} for i in range(0, len(res), 2): options[res[i][1:]] = int(res[i+1]) return options -def families(root=None): + +def families(root=None, displayof=None): "Get font families (as a tuple)" if not root: root = tkinter._default_root - return root.tk.splitlist(root.tk.call("font", "families")) + args = () + if displayof: + args = ('-displayof', displayof) + return root.tk.splitlist(root.tk.call("font", "families", *args)) + def names(root=None): "Get names of defined fonts (as a tuple)" @@ -176,6 +192,7 @@ root = tkinter._default_root return root.tk.splitlist(root.tk.call("font", "names")) + # -------------------------------------------------------------------- # test stuff @@ -198,10 +215,10 @@ print(f.measure("hello"), f.metrics("linespace")) - print(f.metrics()) + print(f.metrics(displayof=root)) f = Font(font=("Courier", 20, "bold")) - print(f.measure("hello"), f.metrics("linespace")) + print(f.measure("hello"), f.metrics("linespace", displayof=root)) w = tkinter.Label(root, text="Hello, world", font=f) w.pack() diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -1253,7 +1253,7 @@ def exists(self, item): - """Returns True if the specified item is present in the three, + """Returns True if the specified item is present in the tree, False otherwise.""" return bool(self.tk.call(self._w, "exists", item)) diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -448,6 +448,14 @@ def register_X_browsers(): + # use xdg-open if around + if _iscommand("xdg-open"): + register("xdg-open", None, BackgroundBrowser("xdg-open")) + + # The default GNOME3 browser + if "GNOME_DESKTOP_SESSION_ID" in os.environ and _iscommand("gvfs-open"): + register("gvfs-open", None, BackgroundBrowser("gvfs-open")) + # The default GNOME browser if "GNOME_DESKTOP_SESSION_ID" in os.environ and _iscommand("gnome-open"): register("gnome-open", None, BackgroundBrowser("gnome-open")) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1351,7 +1351,7 @@ clobber: clean profile-removal -rm -f $(BUILDPYTHON) $(PGEN) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \ - tags TAGS Parser/pgen.stamp \ + tags TAGS \ config.cache config.log pyconfig.h Modules/config.c -rm -rf build platform -rm -rf $(PYTHONFRAMEWORKDIR) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -333,6 +333,7 @@ John Fouhy Andrew Francis Martin Franklin +Bruce Frederiksen Robin Friedrich Ivan Frohne Matthias Fuchs @@ -976,6 +977,7 @@ Peter Stoehr Casper Stoel Michael Stone +Serhiy Storchaka Ken Stox Dan Stromberg Daniel Stutzbach diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,10 +19,26 @@ Library ------- +- Issue #8515: Set __file__ when run file in IDLE. + Initial patch by Bruce Frederiksen. + +- Issue #14496: Fix wrong name in idlelib/tabbedpages.py. + Patch by Popa Claudiu. + +- Issue #3033: Add displayof parameter to tkinter font. Patch by Guilherme Polo. + +- Issue #14482: Raise a ValueError, not a NameError, when trying to create + a multiprocessing Client or Listener with an AF_UNIX type address under + Windows. Patch by Popa Claudiu. + +- Issue #802310: Generate always unique tkinter font names if not directly passed. + - Issue #14151: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. +- Issue #14493: Use gvfs-open or xdg-open in webbrowser. + What's New in Python 3.3.0 Alpha 2? =================================== @@ -58,6 +74,8 @@ - Issue #14471: Fix a possible buffer overrun in the winreg module. +- Issue #14288: Allow the serialization of builtin iterators + Library ------- @@ -997,7 +1015,7 @@ - Issue #11006: Don't issue low level warning in subprocess when pipe2() fails. -- Issue #13620: Support for Chrome browser in webbrowser.py Patch contributed +- Issue #13620: Support for Chrome browser in webbrowser. Patch contributed by Arnaud Calmettes. - Issue #11829: Fix code execution holes in inspect.getattr_static for diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1122,6 +1122,35 @@ } static PyObject * +dequeiter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + Py_ssize_t i, index=0; + PyObject *deque; + dequeiterobject *it; + if (!PyArg_ParseTuple(args, "O!|n", &deque_type, &deque, &index)) + return NULL; + assert(type == &dequeiter_type); + + it = (dequeiterobject*)deque_iter((dequeobject *)deque); + if (!it) + return NULL; + /* consume items from the queue */ + for(i=0; icounter) { + Py_DECREF(it); + return NULL; + } else + break; + } + } + return (PyObject*)it; +} + +static PyObject * dequeiter_len(dequeiterobject *it) { return PyLong_FromSsize_t(it->counter); @@ -1129,14 +1158,21 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +dequeiter_reduce(dequeiterobject *it) +{ + return Py_BuildValue("O(On)", Py_TYPE(it), it->deque, it->deque->len - it->counter); +} + static PyMethodDef dequeiter_methods[] = { {"__length_hint__", (PyCFunction)dequeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)dequeiter_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; static PyTypeObject dequeiter_type = { PyVarObject_HEAD_INIT(NULL, 0) - "deque_iterator", /* tp_name */ + "_collections._deque_iterator", /* tp_name */ sizeof(dequeiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -1164,6 +1200,16 @@ PyObject_SelfIter, /* tp_iter */ (iternextfunc)dequeiter_next, /* tp_iternext */ dequeiter_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 */ + dequeiter_new, /* tp_new */ 0, }; @@ -1217,9 +1263,38 @@ return item; } +static PyObject * +dequereviter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + Py_ssize_t i, index=0; + PyObject *deque; + dequeiterobject *it; + if (!PyArg_ParseTuple(args, "O!|n", &deque_type, &deque, &index)) + return NULL; + assert(type == &dequereviter_type); + + it = (dequeiterobject*)deque_reviter((dequeobject *)deque); + if (!it) + return NULL; + /* consume items from the queue */ + for(i=0; icounter) { + Py_DECREF(it); + return NULL; + } else + break; + } + } + return (PyObject*)it; +} + static PyTypeObject dequereviter_type = { PyVarObject_HEAD_INIT(NULL, 0) - "deque_reverse_iterator", /* tp_name */ + "_collections._deque_reverse_iterator", /* tp_name */ sizeof(dequeiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -1247,6 +1322,16 @@ PyObject_SelfIter, /* tp_iter */ (iternextfunc)dequereviter_next, /* tp_iternext */ dequeiter_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 */ + dequereviter_new, /* tp_new */ 0, }; @@ -1653,9 +1738,13 @@ if (PyType_Ready(&dequeiter_type) < 0) return NULL; + Py_INCREF(&dequeiter_type); + PyModule_AddObject(m, "_deque_iterator", (PyObject *)&dequeiter_type); if (PyType_Ready(&dequereviter_type) < 0) return NULL; + Py_INCREF(&dequereviter_type); + PyModule_AddObject(m, "_deque_reverse_iterator", (PyObject *)&dequereviter_type); return m; } diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1935,7 +1935,7 @@ mpd_maxcontext(&maxctx); mpd_qset_string(MPD(dec), s, &maxctx, &status); - if (status & (MPD_Inexact|MPD_Rounded)) { + if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) { /* we want exact results */ mpd_seterror(MPD(dec), MPD_Invalid_operation, &status); } @@ -2139,7 +2139,7 @@ return NULL; } - if (status & (MPD_Inexact|MPD_Rounded)) { + if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) { /* we want exact results */ mpd_seterror(MPD(dec), MPD_Invalid_operation, &status); } @@ -2385,8 +2385,8 @@ } /* coefficient */ - digits = sequence_as_tuple(PyTuple_GET_ITEM(dectuple, 1), - PyExc_ValueError, "coefficient must be a tuple of digits"); + digits = sequence_as_tuple(PyTuple_GET_ITEM(dectuple, 1), PyExc_ValueError, + "coefficient must be a tuple of digits"); if (digits == NULL) { goto error; } @@ -2435,8 +2435,8 @@ if (sign_special[1] == '\0') { /* not a special number */ *cp++ = 'E'; - n = snprintf(cp, MPD_EXPDIGITS+1, "%" PRI_mpd_ssize_t, exp); - if (n < 0 || n >= MPD_EXPDIGITS+1) { + n = snprintf(cp, MPD_EXPDIGITS+2, "%" PRI_mpd_ssize_t, exp); + if (n < 0 || n >= MPD_EXPDIGITS+2) { PyErr_SetString(PyExc_RuntimeError, "internal error in dec_sequence_as_str"); goto error; @@ -4215,7 +4215,7 @@ mpd_uint_t p_data[1] = {2305843009213693951ULL}; mpd_t p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 19, 1, 1, p_data}; /* Inverse of 10 modulo p */ - mpd_uint_t inv10_p_data[2] = {2075258708292324556ULL}; + mpd_uint_t inv10_p_data[1] = {2075258708292324556ULL}; mpd_t inv10_p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 19, 1, 1, inv10_p_data}; #elif defined(CONFIG_32) && _PyHASH_BITS == 31 @@ -4934,7 +4934,7 @@ PyObject *result; CONVERT_OP_RAISE(&result, v, context); - return result; + return result; } static PyObject * diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py --- a/Modules/_decimal/tests/deccheck.py +++ b/Modules/_decimal/tests/deccheck.py @@ -302,6 +302,7 @@ dec = maxcontext.create_decimal(value) if maxcontext.flags[P.Inexact] or \ maxcontext.flags[P.Rounded] or \ + maxcontext.flags[P.Clamped] or \ maxcontext.flags[P.InvalidOperation]: return context.p._raise_error(P.InvalidOperation) if maxcontext.flags[P.FloatOperation]: diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -48,6 +48,7 @@ /* See http://www.python.org/psf/license for licensing details. */ #include "Python.h" +#include "structmember.h" #define VERSION "1.0.6" @@ -229,6 +230,8 @@ ElementObjectExtra* extra; + PyObject *weakreflist; /* For tp_weaklistoffset */ + } ElementObject; static PyTypeObject Element_Type; @@ -261,17 +264,26 @@ LOCAL(void) dealloc_extra(ElementObject* self) { + ElementObjectExtra *myextra; int i; - Py_DECREF(self->extra->attrib); - - for (i = 0; i < self->extra->length; i++) - Py_DECREF(self->extra->children[i]); - - if (self->extra->children != self->extra->_children) - PyObject_Free(self->extra->children); - - PyObject_Free(self->extra); + if (!self->extra) + return; + + /* Avoid DECREFs calling into this code again (cycles, etc.) + */ + myextra = self->extra; + self->extra = NULL; + + Py_DECREF(myextra->attrib); + + for (i = 0; i < myextra->length; i++) + Py_DECREF(myextra->children[i]); + + if (myextra->children != myextra->_children) + PyObject_Free(myextra->children); + + PyObject_Free(myextra); } /* Convenience internal function to create new Element objects with the given @@ -308,6 +320,8 @@ Py_INCREF(Py_None); self->tail = Py_None; + self->weakreflist = NULL; + ALLOC(sizeof(ElementObject), "create element"); PyObject_GC_Track(self); return (PyObject*) self; @@ -328,6 +342,7 @@ e->tail = Py_None; e->extra = NULL; + e->weakreflist = NULL; } return (PyObject *)e; } @@ -576,19 +591,28 @@ static int element_gc_clear(ElementObject *self) { - PyObject *text = JOIN_OBJ(self->text); - PyObject *tail = JOIN_OBJ(self->tail); Py_CLEAR(self->tag); - Py_CLEAR(text); - Py_CLEAR(tail); + + /* The following is like Py_CLEAR for self->text and self->tail, but + * written explicitily because the real pointers hide behind access + * macros. + */ + if (self->text) { + PyObject *tmp = JOIN_OBJ(self->text); + self->text = NULL; + Py_DECREF(tmp); + } + + if (self->tail) { + PyObject *tmp = JOIN_OBJ(self->tail); + self->tail = NULL; + Py_DECREF(tmp); + } /* After dropping all references from extra, it's no longer valid anyway, - ** so fully deallocate it (see also element_clearmethod) + * so fully deallocate it. */ - if (self->extra) { - dealloc_extra(self); - self->extra = NULL; - } + dealloc_extra(self); return 0; } @@ -596,6 +620,10 @@ element_dealloc(ElementObject* self) { PyObject_GC_UnTrack(self); + + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); + /* element_gc_clear clears all references and deallocates extra */ element_gc_clear(self); @@ -626,10 +654,7 @@ if (!PyArg_ParseTuple(args, ":clear")) return NULL; - if (self->extra) { - dealloc_extra(self); - self->extra = NULL; - } + dealloc_extra(self); Py_INCREF(Py_None); Py_DECREF(JOIN_OBJ(self->text)); @@ -1693,7 +1718,7 @@ (traverseproc)element_gc_traverse, /* tp_traverse */ (inquiry)element_gc_clear, /* tp_clear */ 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(ElementObject, weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ element_methods, /* tp_methods */ @@ -3009,8 +3034,7 @@ PyMODINIT_FUNC PyInit__elementtree(void) { - PyObject* m; - PyObject* g; + PyObject *m, *g, *temp; char* bootstrap; /* Initialize object types */ @@ -3042,10 +3066,6 @@ PyDict_SetItemString(g, "__builtins__", PyEval_GetBuiltins()); bootstrap = ( - - "from copy import deepcopy\n" - "from xml.etree import ElementPath\n" - "def iter(node, tag=None):\n" /* helper */ " if tag == '*':\n" " tag = None\n" @@ -3069,8 +3089,14 @@ if (!PyRun_String(bootstrap, Py_file_input, g, NULL)) return NULL; - elementpath_obj = PyDict_GetItemString(g, "ElementPath"); - elementtree_deepcopy_obj = PyDict_GetItemString(g, "deepcopy"); + if (!(temp = PyImport_ImportModule("copy"))) + return NULL; + elementtree_deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy"); + Py_XDECREF(temp); + + if (!(elementpath_obj = PyImport_ImportModule("xml.etree.ElementPath"))) + return NULL; + elementtree_iter_obj = PyDict_GetItemString(g, "iter"); elementtree_itertext_obj = PyDict_GetItemString(g, "itertext"); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2753,6 +2753,34 @@ return 0; } +static PyObject * +arrayiter_reduce(arrayiterobject *it) +{ + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), + it->ao, it->index); +} + +static PyObject * +arrayiter_setstate(arrayiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); +static PyMethodDef arrayiter_methods[] = { + {"__reduce__", (PyCFunction)arrayiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)arrayiter_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + static PyTypeObject PyArrayIter_Type = { PyVarObject_HEAD_INIT(NULL, 0) "arrayiterator", /* tp_name */ @@ -2782,7 +2810,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)arrayiter_next, /* tp_iternext */ - 0, /* tp_methods */ + arrayiter_methods, /* tp_methods */ }; diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -134,6 +134,53 @@ return r; } +static PyObject * +groupby_reduce(groupbyobject *lz) +{ + /* reduce as a 'new' call with an optional 'setstate' if groupby + * has started + */ + PyObject *value; + if (lz->tgtkey && lz->currkey && lz->currvalue) + value = Py_BuildValue("O(OO)(OOO)", Py_TYPE(lz), + lz->it, lz->keyfunc, lz->currkey, lz->currvalue, lz->tgtkey); + else + value = Py_BuildValue("O(OO)", Py_TYPE(lz), + lz->it, lz->keyfunc); + + return value; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +groupby_setstate(groupbyobject *lz, PyObject *state) +{ + PyObject *currkey, *currvalue, *tgtkey; + if (!PyArg_ParseTuple(state, "OOO", &currkey, &currvalue, &tgtkey)) + return NULL; + Py_CLEAR(lz->currkey); + lz->currkey = currkey; + Py_INCREF(lz->currkey); + Py_CLEAR(lz->currvalue); + lz->currvalue = currvalue; + Py_INCREF(lz->currvalue); + Py_CLEAR(lz->tgtkey); + lz->tgtkey = tgtkey; + Py_INCREF(lz->tgtkey); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + +static PyMethodDef groupby_methods[] = { + {"__reduce__", (PyCFunction)groupby_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)groupby_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(groupby_doc, "groupby(iterable[, keyfunc]) -> create an iterator which returns\n\ (key, sub-iterator) grouped by each value of key(value).\n"); @@ -168,7 +215,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)groupby_next, /* tp_iternext */ - 0, /* tp_methods */ + groupby_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -194,6 +241,17 @@ static PyTypeObject _grouper_type; static PyObject * +_grouper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *parent, *tgtkey; + + if (!PyArg_ParseTuple(args, "O!O", &groupby_type, &parent, &tgtkey)) + return NULL; + + return _grouper_create((groupbyobject*) parent, tgtkey); +} + +static PyObject * _grouper_create(groupbyobject *parent, PyObject *tgtkey) { _grouperobject *igo; @@ -269,6 +327,20 @@ return r; } +static PyObject * +_grouper_reduce(_grouperobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), + lz->parent, lz->tgtkey); +} + +static PyMethodDef _grouper_methods[] = { + {"__reduce__", (PyCFunction)_grouper_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + + static PyTypeObject _grouper_type = { PyVarObject_HEAD_INIT(NULL, 0) "itertools._grouper", /* tp_name */ @@ -298,7 +370,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)_grouper_next, /* tp_iternext */ - 0, /* tp_methods */ + _grouper_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -308,7 +380,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - 0, /* tp_new */ + _grouper_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -344,7 +416,7 @@ static PyTypeObject teedataobject_type; static PyObject * -teedataobject_new(PyObject *it) +teedataobject_newinternal(PyObject *it) { teedataobject *tdo; @@ -364,7 +436,7 @@ teedataobject_jumplink(teedataobject *tdo) { if (tdo->nextlink == NULL) - tdo->nextlink = teedataobject_new(tdo->it); + tdo->nextlink = teedataobject_newinternal(tdo->it); Py_XINCREF(tdo->nextlink); return tdo->nextlink; } @@ -420,11 +492,80 @@ PyObject_GC_Del(tdo); } +static PyObject * +teedataobject_reduce(teedataobject *tdo) +{ + 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++) { + Py_INCREF(tdo->values[i]); + PyList_SET_ITEM(values, i, tdo->values[i]); + } + return Py_BuildValue("O(ONO)", Py_TYPE(tdo), tdo->it, + values, + tdo->nextlink ? tdo->nextlink : Py_None); +} + +static PyTypeObject teedataobject_type; + +static PyObject * +teedataobject_new(PyTypeObject *type, PyObject *args, PyObject *kw) +{ + teedataobject *tdo; + PyObject *it, *values, *next; + Py_ssize_t i, len; + + assert(type == &teedataobject_type); + if (!PyArg_ParseTuple(args, "OO!O", &it, &PyList_Type, &values, &next)) + return NULL; + + tdo = (teedataobject *)teedataobject_newinternal(it); + if (!tdo) + return NULL; + + len = PyList_GET_SIZE(values); + if (len > LINKCELLS) + goto err; + for (i=0; ivalues[i] = PyList_GET_ITEM(values, i); + Py_INCREF(tdo->values[i]); + } + tdo->numread = len; + + if (len == LINKCELLS) { + if (next != Py_None) { + if (Py_TYPE(next) != &teedataobject_type) + goto err; + assert(tdo->nextlink == NULL); + Py_INCREF(next); + tdo->nextlink = next; + } + } else { + if (next != Py_None) + goto err; /* shouldn't have a next if we are not full */ + } + return (PyObject*)tdo; + +err: + Py_XDECREF(tdo); + PyErr_SetString(PyExc_ValueError, "Invalid arguments"); + return NULL; +} + +static PyMethodDef teedataobject_methods[] = { + {"__reduce__", (PyCFunction)teedataobject_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + 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 */ - "itertools.tee_dataobject", /* tp_name */ + "itertools._tee_dataobject", /* tp_name */ sizeof(teedataobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -451,7 +592,7 @@ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + teedataobject_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -461,7 +602,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - 0, /* tp_new */ + teedataobject_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -528,7 +669,7 @@ to = PyObject_GC_New(teeobject, &tee_type); if (to == NULL) goto done; - to->dataobj = (teedataobject *)teedataobject_new(it); + to->dataobj = (teedataobject *)teedataobject_newinternal(it); if (!to->dataobj) { PyObject_GC_Del(to); to = NULL; @@ -548,7 +689,7 @@ { PyObject *iterable; - if (!PyArg_UnpackTuple(args, "tee", 1, 1, &iterable)) + if (!PyArg_UnpackTuple(args, "_tee", 1, 1, &iterable)) return NULL; return tee_fromiterable(iterable); } @@ -570,17 +711,43 @@ PyObject_GC_Del(to); } +static PyObject * +tee_reduce(teeobject *to) +{ + return Py_BuildValue("O(())(Oi)", Py_TYPE(to), to->dataobj, to->index); +} + +static PyObject * +tee_setstate(teeobject *to, PyObject *state) +{ + teedataobject *tdo; + int index; + if (!PyArg_ParseTuple(state, "O!i", &teedataobject_type, &tdo, &index)) + return NULL; + if (index < 0 || index > LINKCELLS) { + PyErr_SetString(PyExc_ValueError, "Index out of range"); + return NULL; + } + Py_CLEAR(to->dataobj); + to->dataobj = tdo; + Py_INCREF(to->dataobj); + to->index = index; + Py_RETURN_NONE; +} + PyDoc_STRVAR(teeobject_doc, "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}, {NULL, NULL} /* sentinel */ }; static PyTypeObject tee_type = { PyVarObject_HEAD_INIT(NULL, 0) - "itertools.tee", /* tp_name */ + "itertools._tee", /* tp_name */ sizeof(teeobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -771,6 +938,38 @@ } } +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); + } + +static PyObject * +cycle_setstate(cycleobject *lz, PyObject *state) +{ + PyObject *saved=NULL; + int firstpass; + if (!PyArg_ParseTuple(state, "Oi", &saved, &firstpass)) + return NULL; + Py_CLEAR(lz->saved); + lz->saved = saved; + Py_XINCREF(lz->saved); + lz->firstpass = firstpass != 0; + Py_RETURN_NONE; +} + +static PyMethodDef cycle_methods[] = { + {"__reduce__", (PyCFunction)cycle_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)cycle_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(cycle_doc, "cycle(iterable) --> cycle object\n\ \n\ @@ -807,7 +1006,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)cycle_next, /* tp_iternext */ - 0, /* tp_methods */ + cycle_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -913,6 +1112,31 @@ } } +static PyObject * +dropwhile_reduce(dropwhileobject *lz) +{ + return Py_BuildValue("O(OO)l", Py_TYPE(lz), + lz->func, lz->it, lz->start); +} + +static PyObject * +dropwhile_setstate(dropwhileobject *lz, PyObject *state) +{ + int start = PyObject_IsTrue(state); + if (start == -1) + return NULL; + lz->start = start; + Py_RETURN_NONE; +} + +static PyMethodDef dropwhile_methods[] = { + {"__reduce__", (PyCFunction)dropwhile_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)dropwhile_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(dropwhile_doc, "dropwhile(predicate, iterable) --> dropwhile object\n\ \n\ @@ -949,7 +1173,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)dropwhile_next, /* tp_iternext */ - 0, /* tp_methods */ + dropwhile_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1052,6 +1276,30 @@ return NULL; } +static PyObject * +takewhile_reduce(takewhileobject *lz) +{ + 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 == -1) + return NULL; + lz->stop = stop; + Py_RETURN_NONE; +} + +static PyMethodDef takewhile_reduce_methods[] = { + {"__reduce__", (PyCFunction)takewhile_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)takewhile_reduce_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; PyDoc_STRVAR(takewhile_doc, "takewhile(predicate, iterable) --> takewhile object\n\ \n\ @@ -1088,7 +1336,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)takewhile_next, /* tp_iternext */ - 0, /* tp_methods */ + takewhile_reduce_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1244,6 +1492,44 @@ return item; } +static PyObject * +islice_reduce(isliceobject *lz) +{ + /* When unpickled, generate a new object with the same bounds, + * then 'setstate' with the next and count + */ + PyObject *stop; + if (lz->stop == -1) { + stop = Py_None; + Py_INCREF(stop); + } else { + stop = PyLong_FromSsize_t(lz->stop); + if (stop == NULL) + return NULL; + } + return Py_BuildValue("O(OnNn)n", Py_TYPE(lz), + lz->it, lz->next, stop, lz->step, + lz->cnt); +} + +static PyObject * +islice_setstate(isliceobject *lz, PyObject *state) +{ + Py_ssize_t cnt = PyLong_AsSsize_t(state); + if (cnt == -1 && PyErr_Occurred()) + return NULL; + lz->cnt = cnt; + Py_RETURN_NONE; +} + +static PyMethodDef islice_methods[] = { + {"__reduce__", (PyCFunction)islice_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)islice_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(islice_doc, "islice(iterable, [start,] stop [, step]) --> islice object\n\ \n\ @@ -1284,7 +1570,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)islice_next, /* tp_iternext */ - 0, /* tp_methods */ + islice_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1379,6 +1665,19 @@ return result; } +static PyObject * +starmap_reduce(starmapobject *lz) +{ + /* Just pickle the iterator */ + return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->func, lz->it); +} + +static PyMethodDef starmap_methods[] = { + {"__reduce__", (PyCFunction)starmap_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(starmap_doc, "starmap(function, sequence) --> starmap object\n\ \n\ @@ -1415,7 +1714,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)starmap_next, /* tp_iternext */ - 0, /* tp_methods */ + starmap_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1534,6 +1833,41 @@ return chain_next(lz); /* recurse and use next active */ } +static PyObject * +chain_reduce(chainobject *lz) +{ + if (lz->source) { + /* we can't pickle function objects (itertools.from_iterable) so + * we must use setstate to replace the iterable. One day we + * will fix pickling of functions + */ + if (lz->active) { + return Py_BuildValue("O()(OO)", Py_TYPE(lz), lz->source, lz->active); + } else { + return Py_BuildValue("O()(O)", Py_TYPE(lz), lz->source); + } + } else { + return Py_BuildValue("O()", Py_TYPE(lz)); /* exhausted */ + } + return NULL; +} + +static PyObject * +chain_setstate(chainobject *lz, PyObject *state) +{ + PyObject *source, *active=NULL; + if (! PyArg_ParseTuple(state, "O|O", &source, &active)) + return NULL; + + Py_CLEAR(lz->source); + lz->source = source; + Py_INCREF(lz->source); + Py_CLEAR(lz->active); + lz->active = active; + Py_XINCREF(lz->active); + Py_RETURN_NONE; +} + PyDoc_STRVAR(chain_doc, "chain(*iterables) --> chain object\n\ \n\ @@ -1550,6 +1884,10 @@ static PyMethodDef chain_methods[] = { {"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, + setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -1790,6 +2128,83 @@ return NULL; } +static PyObject * +product_reduce(productobject *lz) +{ + if (lz->stopped) { + return Py_BuildValue("O(())", Py_TYPE(lz)); + } else if (lz->result == NULL) { + return Py_BuildValue("OO", Py_TYPE(lz), lz->pools); + } else { + PyObject *indices; + Py_ssize_t n, i; + + /* we must pickle the indices use them for setstate, and + * additionally indicate that the iterator has started + */ + n = PyTuple_GET_SIZE(lz->pools); + indices = PyTuple_New(n); + if (indices == NULL) + return NULL; + for (i=0; iindices[i]); + if (!index) { + Py_DECREF(indices); + return NULL; + } + PyTuple_SET_ITEM(indices, i, index); + } + return Py_BuildValue("OON", Py_TYPE(lz), lz->pools, indices); + } +} + +static PyObject * +product_setstate(productobject *lz, PyObject *state) +{ + PyObject *result; + Py_ssize_t n, i; + + n = PyTuple_GET_SIZE(lz->pools); + if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != n) { + PyErr_SetString(PyExc_ValueError, "invalid arguments"); + return NULL; + } + for (i=0; i n-1) + index = n-1; + lz->indices[i] = index; + } + + result = PyTuple_New(n); + if (!result) + return NULL; + for (i=0; ipools, i); + PyObject *element = PyTuple_GET_ITEM(pool, lz->indices[i]); + Py_INCREF(element); + PyTuple_SET_ITEM(result, i, element); + } + Py_CLEAR(lz->result); + lz->result = result; + Py_RETURN_NONE; +} + +static PyMethodDef product_methods[] = { + {"__reduce__", (PyCFunction)product_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)product_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(product_doc, "product(*iterables) --> product object\n\ \n\ @@ -1834,7 +2249,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)product_next, /* tp_iternext */ - 0, /* tp_methods */ + product_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2021,6 +2436,86 @@ return NULL; } +static PyObject * +combinations_reduce(combinationsobject *lz) +{ + if (lz->result == NULL) { + return Py_BuildValue("O(On)", Py_TYPE(lz), lz->pool, lz->r); + } else if (lz->stopped) { + return Py_BuildValue("O(()n)", Py_TYPE(lz), lz->r); + } else { + PyObject *indices; + Py_ssize_t i; + + /* we must pickle the indices and use them for setstate */ + indices = PyTuple_New(lz->r); + if (!indices) + return NULL; + for (i=0; ir; i++) + { + PyObject* index = PyLong_FromSsize_t(lz->indices[i]); + if (!index) { + Py_DECREF(indices); + return NULL; + } + PyTuple_SET_ITEM(indices, i, index); + } + + return Py_BuildValue("O(On)N", Py_TYPE(lz), lz->pool, lz->r, indices); + } +} + +static PyObject * +combinations_setstate(combinationsobject *lz, PyObject *state) +{ + PyObject *result; + Py_ssize_t i; + Py_ssize_t n = PyTuple_GET_SIZE(lz->pool); + + if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != lz->r) + { + PyErr_SetString(PyExc_ValueError, "invalid arguments"); + return NULL; + } + + 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; + /* clamp the index (beware of negative max) */ + if (index > max) + index = max; + if (index < 0) + index = 0; + lz->indices[i] = index; + } + + result = PyTuple_New(lz->r); + if (result == NULL) + return NULL; + for (i=0; ir; i++) { + PyObject *element = PyTuple_GET_ITEM(lz->pool, lz->indices[i]); + Py_INCREF(element); + PyTuple_SET_ITEM(result, i, element); + } + + Py_CLEAR(lz->result); + lz->result = result; + Py_RETURN_NONE; +} + +static PyMethodDef combinations_methods[] = { + {"__reduce__", (PyCFunction)combinations_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)combinations_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(combinations_doc, "combinations(iterable, r) --> combinations object\n\ \n\ @@ -2029,11 +2524,11 @@ static PyTypeObject combinations_type = { PyVarObject_HEAD_INIT(NULL, 0) - "itertools.combinations", /* tp_name */ + "itertools.combinations", /* tp_name */ sizeof(combinationsobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)combinations_dealloc, /* tp_dealloc */ + (destructor)combinations_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -2050,14 +2545,14 @@ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ - combinations_doc, /* tp_doc */ - (traverseproc)combinations_traverse, /* tp_traverse */ + combinations_doc, /* tp_doc */ + (traverseproc)combinations_traverse,/* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)combinations_next, /* tp_iternext */ - 0, /* tp_methods */ + (iternextfunc)combinations_next, /* tp_iternext */ + combinations_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2067,7 +2562,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - combinations_new, /* tp_new */ + combinations_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -2266,6 +2761,82 @@ return NULL; } +static PyObject * +cwr_reduce(cwrobject *lz) +{ + if (lz->result == NULL) { + return Py_BuildValue("O(On)", Py_TYPE(lz), lz->pool, lz->r); + } else if (lz->stopped) { + return Py_BuildValue("O(()n)", Py_TYPE(lz), lz->r); + } else { + PyObject *indices; + Py_ssize_t i; + + /* we must pickle the indices and use them for setstate */ + indices = PyTuple_New(lz->r); + if (!indices) + return NULL; + for (i=0; ir; i++) + { + PyObject* index = PyLong_FromSsize_t(lz->indices[i]); + if (!index) { + Py_DECREF(indices); + return NULL; + } + PyTuple_SET_ITEM(indices, i, index); + } + + return Py_BuildValue("O(On)N", Py_TYPE(lz), lz->pool, lz->r, indices); + } +} + +static PyObject * +cwr_setstate(cwrobject *lz, PyObject *state) +{ + PyObject *result; + Py_ssize_t n, i; + + if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != lz->r) + { + PyErr_SetString(PyExc_ValueError, "invalid arguments"); + return NULL; + } + + n = PyTuple_GET_SIZE(lz->pool); + 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 */ + if (index < 0) + index = 0; + else if (index > n-1) + index = n-1; + lz->indices[i] = index; + } + result = PyTuple_New(lz->r); + if (result == NULL) + return NULL; + for (i=0; ir; i++) { + PyObject *element = PyTuple_GET_ITEM(lz->pool, lz->indices[i]); + Py_INCREF(element); + PyTuple_SET_ITEM(result, i, element); + } + Py_CLEAR(lz->result); + lz->result = result; + Py_RETURN_NONE; +} + +static PyMethodDef cwr_methods[] = { + {"__reduce__", (PyCFunction)cwr_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)cwr_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(cwr_doc, "combinations_with_replacement(iterable, r) --> combinations_with_replacement object\n\ \n\ @@ -2275,11 +2846,11 @@ static PyTypeObject cwr_type = { PyVarObject_HEAD_INIT(NULL, 0) - "itertools.combinations_with_replacement", /* tp_name */ - sizeof(cwrobject), /* tp_basicsize */ + "itertools.combinations_with_replacement", /* tp_name */ + sizeof(cwrobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)cwr_dealloc, /* tp_dealloc */ + (destructor)cwr_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -2291,19 +2862,19 @@ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - cwr_doc, /* tp_doc */ - (traverseproc)cwr_traverse, /* tp_traverse */ + Py_TPFLAGS_BASETYPE, /* tp_flags */ + cwr_doc, /* tp_doc */ + (traverseproc)cwr_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)cwr_next, /* tp_iternext */ - 0, /* tp_methods */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)cwr_next, /* tp_iternext */ + cwr_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2313,8 +2884,8 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - cwr_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + cwr_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; @@ -2538,6 +3109,115 @@ return NULL; } +static PyObject * +permutations_reduce(permutationsobject *po) +{ + if (po->result == NULL) { + return Py_BuildValue("O(On)", Py_TYPE(po), po->pool, po->r); + } else if (po->stopped) { + return Py_BuildValue("O(()n)", Py_TYPE(po), po->r); + } else { + PyObject *indices=NULL, *cycles=NULL; + Py_ssize_t n, i; + + /* we must pickle the indices and cycles and use them for setstate */ + n = PyTuple_GET_SIZE(po->pool); + indices = PyTuple_New(n); + if (indices == NULL) + goto err; + for (i=0; iindices[i]); + if (!index) + goto err; + PyTuple_SET_ITEM(indices, i, index); + } + + cycles = PyTuple_New(po->r); + if (cycles == NULL) + goto err; + for (i=0; ir; i++) + { + PyObject* index = PyLong_FromSsize_t(po->cycles[i]); + if (!index) + goto err; + PyTuple_SET_ITEM(cycles, i, index); + } + return Py_BuildValue("O(On)(NN)", Py_TYPE(po), + po->pool, po->r, + indices, cycles); + err: + Py_XDECREF(indices); + Py_XDECREF(cycles); + return NULL; + } +} + +static PyObject * +permutations_setstate(permutationsobject *po, PyObject *state) +{ + PyObject *indices, *cycles, *result; + Py_ssize_t n, i; + + if (!PyArg_ParseTuple(state, "O!O!", + &PyTuple_Type, &indices, + &PyTuple_Type, &cycles)) + return NULL; + + n = PyTuple_GET_SIZE(po->pool); + if (PyTuple_GET_SIZE(indices) != n || + PyTuple_GET_SIZE(cycles) != po->r) + { + PyErr_SetString(PyExc_ValueError, "invalid arguments"); + return NULL; + } + + for (i=0; i n-1) + index = n-1; + po->indices[i] = index; + } + + 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()) + return NULL; /* not an integer */ + if (index < 1) + index = 1; + else if (index > n-i) + index = n-i; + po->cycles[i] = index; + } + result = PyTuple_New(po->r); + if (result == NULL) + return NULL; + for (i=0; ir; i++) { + PyObject *element = PyTuple_GET_ITEM(po->pool, po->indices[i]); + Py_INCREF(element); + PyTuple_SET_ITEM(result, i, element); + } + Py_CLEAR(po->result); + po->result = result; + Py_RETURN_NONE; +} + +static PyMethodDef permuations_methods[] = { + {"__reduce__", (PyCFunction)permutations_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)permutations_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(permutations_doc, "permutations(iterable[, r]) --> permutations object\n\ \n\ @@ -2574,7 +3254,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)permutations_next, /* tp_iternext */ - 0, /* tp_methods */ + permuations_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2605,7 +3285,7 @@ static char *kwargs[] = {"iterable", "func", NULL}; PyObject *iterable; PyObject *it; - PyObject *binop = NULL; + PyObject *binop = Py_None; accumulateobject *lz; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:accumulate", @@ -2624,8 +3304,10 @@ return NULL; } - Py_XINCREF(binop); - lz->binop = binop; + if (binop != Py_None) { + Py_XINCREF(binop); + lz->binop = binop; + } lz->total = NULL; lz->it = it; return (PyObject *)lz; @@ -2681,6 +3363,31 @@ return newtotal; } +static PyObject * +accumulate_reduce(accumulateobject *lz) +{ + 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) +{ + Py_CLEAR(lz->total); + lz->total = state; + Py_INCREF(lz->total); + Py_RETURN_NONE; +} + +static PyMethodDef accumulate_methods[] = { + {"__reduce__", (PyCFunction)accumulate_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)accumulate_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(accumulate_doc, "accumulate(iterable[, func]) --> accumulate object\n\ \n\ @@ -2716,7 +3423,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)accumulate_next, /* tp_iternext */ - 0, /* tp_methods */ + accumulate_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2833,6 +3540,19 @@ } } +static PyObject * +compress_reduce(compressobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), + lz->data, lz->selectors); + } + +static PyMethodDef compress_methods[] = { + {"__reduce__", (PyCFunction)compress_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(compress_doc, "compress(data, selectors) --> iterator over selected data\n\ \n\ @@ -2870,7 +3590,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)compress_next, /* tp_iternext */ - 0, /* tp_methods */ + compress_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2977,6 +3697,19 @@ } } +static PyObject * +filterfalse_reduce(filterfalseobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), + lz->func, lz->it); + } + +static PyMethodDef filterfalse_methods[] = { + {"__reduce__", (PyCFunction)filterfalse_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(filterfalse_doc, "filterfalse(function or None, sequence) --> filterfalse object\n\ \n\ @@ -3013,7 +3746,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)filterfalse_next, /* tp_iternext */ - 0, /* tp_methods */ + filterfalse_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -3207,11 +3940,9 @@ return Py_BuildValue("O(n)", Py_TYPE(lz), lz->cnt); } -PyDoc_STRVAR(count_reduce_doc, "Return state information for pickling."); - static PyMethodDef count_methods[] = { {"__reduce__", (PyCFunction)count_reduce, METH_NOARGS, - count_reduce_doc}, + reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -3352,8 +4083,21 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +repeat_reduce(repeatobject *ro) +{ + /* unpickle this so that a new repeat iterator is constructed with an + * object, then call __setstate__ on it to set cnt + */ + if (ro->cnt >= 0) + return Py_BuildValue("O(On)", Py_TYPE(ro), ro->element, ro->cnt); + else + return Py_BuildValue("O(O)", Py_TYPE(ro), ro->element); +} + static PyMethodDef repeat_methods[] = { {"__length_hint__", (PyCFunction)repeat_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)repeat_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -3579,6 +4323,49 @@ return result; } +static PyObject * +zip_longest_reduce(ziplongestobject *lz) +{ + + /* Create a new tuple with empty sequences where appropriate to pickle. + * Then use setstate to set the fillvalue + */ + int i; + PyObject *args = PyTuple_New(PyTuple_GET_SIZE(lz->ittuple)); + if (args == NULL) + return NULL; + for (i=0; iittuple); i++) { + PyObject *elem = PyTuple_GET_ITEM(lz->ittuple, i); + if (elem == NULL) { + elem = PyTuple_New(0); + if (elem == NULL) { + Py_DECREF(args); + return NULL; + } + } else + Py_INCREF(elem); + PyTuple_SET_ITEM(args, i, elem); + } + return Py_BuildValue("ONO", Py_TYPE(lz), args, lz->fillvalue); +} + +static PyObject * +zip_longest_setstate(ziplongestobject *lz, PyObject *state) +{ + Py_CLEAR(lz->fillvalue); + lz->fillvalue = state; + Py_INCREF(lz->fillvalue); + Py_RETURN_NONE; +} + +static PyMethodDef zip_longest_methods[] = { + {"__reduce__", (PyCFunction)zip_longest_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)zip_longest_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(zip_longest_doc, "zip_longest(iter1 [,iter2 [...]], [fillvalue=None]) --> zip_longest object\n\ \n\ @@ -3620,7 +4407,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)zip_longest_next, /* tp_iternext */ - 0, /* tp_methods */ + zip_longest_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -3708,6 +4495,9 @@ &product_type, &repeat_type, &groupby_type, + &_grouper_type, + &tee_type, + &teedataobject_type, NULL }; @@ -3725,11 +4515,5 @@ PyModule_AddObject(m, name+1, (PyObject *)typelist[i]); } - if (PyType_Ready(&teedataobject_type) < 0) - return NULL; - if (PyType_Ready(&tee_type) < 0) - return NULL; - if (PyType_Ready(&_grouper_type) < 0) - return NULL; return m; } diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -3003,7 +3003,7 @@ } static PyObject * -bytesarrayiter_length_hint(bytesiterobject *it) +bytearrayiter_length_hint(bytesiterobject *it) { Py_ssize_t len = 0; if (it->it_seq) @@ -3014,9 +3014,41 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +bytearrayiter_reduce(bytesiterobject *it) +{ + if (it->it_seq != NULL) { + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), + it->it_seq, it->it_index); + } else { + PyObject *u = PyUnicode_FromUnicode(NULL, 0); + if (u == NULL) + return NULL; + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), u); + } +} + +static PyObject * +bytearrayiter_setstate(bytesiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->it_index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef bytearrayiter_methods[] = { - {"__length_hint__", (PyCFunction)bytesarrayiter_length_hint, METH_NOARGS, + {"__length_hint__", (PyCFunction)bytearrayiter_length_hint, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)bytearrayiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)bytearrayiter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3074,9 +3074,43 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +striter_reduce(striterobject *it) +{ + if (it->it_seq != NULL) { + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), + it->it_seq, it->it_index); + } else { + PyObject *u = PyUnicode_FromUnicode(NULL, 0); + if (u == NULL) + return NULL; + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), u); + } +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +striter_setstate(striterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->it_index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef striter_methods[] = { {"__length_hint__", (PyCFunction)striter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)striter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)striter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2323,9 +2323,16 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +dictiter_reduce(dictiterobject *di); + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + static PyMethodDef dictiter_methods[] = { {"__length_hint__", (PyCFunction)dictiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)dictiter_reduce, METH_NOARGS, + reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -2560,6 +2567,52 @@ }; +static PyObject * +dictiter_reduce(dictiterobject *di) +{ + PyObject *list; + dictiterobject tmp; + + list = PyList_New(0); + if (!list) + return NULL; + + /* copy the itertor state */ + tmp = *di; + Py_XINCREF(tmp.di_dict); + + /* iterate the temporary into a list */ + for(;;) { + PyObject *element = 0; + if (Py_TYPE(di) == &PyDictIterItem_Type) + element = dictiter_iternextitem(&tmp); + else if (Py_TYPE(di) == &PyDictIterKey_Type) + element = dictiter_iternextkey(&tmp); + else if (Py_TYPE(di) == &PyDictIterValue_Type) + element = dictiter_iternextvalue(&tmp); + else + assert(0); + if (element) { + if (PyList_Append(list, element)) { + Py_DECREF(element); + Py_DECREF(list); + Py_XDECREF(tmp.di_dict); + return NULL; + } + Py_DECREF(element); + } else + break; + } + Py_XDECREF(tmp.di_dict); + /* check for error */ + if (tmp.di_dict != NULL) { + /* we have an error */ + Py_DECREF(list); + return NULL; + } + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); +} + /***********************************************/ /* View objects for keys(), items(), values(). */ /***********************************************/ diff --git a/Objects/enumobject.c b/Objects/enumobject.c --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -158,6 +158,22 @@ return result; } +static PyObject * +enum_reduce(enumobject *en) +{ + if (en->en_longindex != NULL) + return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex); + else + return Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyMethodDef enum_methods[] = { + {"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(enum_doc, "enumerate(iterable[, start]) -> iterator for index, value of iterable\n" "\n" @@ -197,7 +213,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)enum_next, /* tp_iternext */ - 0, /* tp_methods */ + enum_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -319,8 +335,40 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +reversed_reduce(reversedobject *ro) +{ + if (ro->seq) + return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index); + else + return Py_BuildValue("O(())", Py_TYPE(ro)); +} + +static PyObject * +reversed_setstate(reversedobject *ro, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (ro->seq != 0) { + Py_ssize_t n = PySequence_Size(ro->seq); + if (n < 0) + return NULL; + if (index < -1) + index = -1; + else if (index > n-1) + index = n-1; + ro->index = index; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef reversediter_methods[] = { {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/iterobject.c b/Objects/iterobject.c --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -88,8 +88,38 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +iter_reduce(seqiterobject *it) +{ + if (it->it_seq != NULL) + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), + it->it_seq, it->it_index); + else + return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter")); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +iter_setstate(seqiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < 0) + index = 0; + it->it_index = index; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef seqiter_methods[] = { {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -195,6 +225,21 @@ return NULL; } +static PyObject * +calliter_reduce(calliterobject *it) +{ + if (it->it_callable != NULL && it->it_sentinel != NULL) + return Py_BuildValue("N(OO)", _PyObject_GetBuiltin("iter"), + it->it_callable, it->it_sentinel); + else + return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter")); +} + +static PyMethodDef calliter_methods[] = { + {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyTypeObject PyCallIter_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "callable_iterator", /* tp_name */ @@ -224,7 +269,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)calliter_iternext, /* tp_iternext */ - 0, /* tp_methods */ + calliter_methods, /* tp_methods */ }; diff --git a/Objects/listobject.c b/Objects/listobject.c --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2660,11 +2660,18 @@ static int listiter_traverse(listiterobject *, visitproc, void *); static PyObject *listiter_next(listiterobject *); static PyObject *listiter_len(listiterobject *); +static PyObject *listiter_reduce_general(void *_it, int forward); +static PyObject *listiter_reduce(listiterobject *); +static PyObject *listiter_setstate(listiterobject *, PyObject *state); PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); static PyMethodDef listiter_methods[] = { {"__length_hint__", (PyCFunction)listiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)listiter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)listiter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -2771,6 +2778,27 @@ } return PyLong_FromLong(0); } + +static PyObject * +listiter_reduce(listiterobject *it) +{ + return listiter_reduce_general(it, 1); +} + +static PyObject * +listiter_setstate(listiterobject *it, PyObject *state) +{ + long index = PyLong_AsLong(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < 0) + index = 0; + it->it_index = index; + } + Py_RETURN_NONE; +} + /*********************** List Reverse Iterator **************************/ typedef struct { @@ -2784,9 +2812,13 @@ static int listreviter_traverse(listreviterobject *, visitproc, void *); static PyObject *listreviter_next(listreviterobject *); static PyObject *listreviter_len(listreviterobject *); +static PyObject *listreviter_reduce(listreviterobject *); +static PyObject *listreviter_setstate(listreviterobject *, PyObject *); static PyMethodDef listreviter_methods[] = { {"__length_hint__", (PyCFunction)listreviter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)listreviter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)listreviter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -2883,3 +2915,51 @@ len = 0; return PyLong_FromSsize_t(len); } + +static PyObject * +listreviter_reduce(listreviterobject *it) +{ + return listiter_reduce_general(it, 0); +} + +static PyObject * +listreviter_setstate(listreviterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < -1) + index = -1; + else if (index > PyList_GET_SIZE(it->it_seq) - 1) + index = PyList_GET_SIZE(it->it_seq) - 1; + it->it_index = index; + } + Py_RETURN_NONE; +} + +/* common pickling support */ + +static PyObject * +listiter_reduce_general(void *_it, int forward) +{ + PyObject *list; + + /* the objects are not the same, index is of different types! */ + if (forward) { + listiterobject *it = (listiterobject *)_it; + if (it->it_seq) + return Py_BuildValue("N(O)l", _PyObject_GetBuiltin("iter"), + it->it_seq, it->it_index); + } else { + listreviterobject *it = (listreviterobject *)_it; + if (it->it_seq) + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("reversed"), + it->it_seq, it->it_index); + } + /* empty iterator, create an empty list */ + list = PyList_New(0); + if (list == NULL) + return NULL; + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); +} diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1026,6 +1026,19 @@ return obj; } +/* Convenience function to get a builtin from its name */ +PyObject * +_PyObject_GetBuiltin(const char *name) +{ + PyObject *mod, *attr; + mod = PyImport_ImportModule("builtins"); + if (mod == NULL) + return NULL; + attr = PyObject_GetAttrString(mod, name); + Py_DECREF(mod); + return attr; +} + /* Helper used when the __next__ method is removed from a type: tp_iternext is never NULL and can be safely called without checking on every iteration. diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -964,9 +964,59 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +rangeiter_reduce(rangeiterobject *r) +{ + PyObject *start=NULL, *stop=NULL, *step=NULL; + PyObject *range; + + /* create a range object for pickling */ + start = PyLong_FromLong(r->start); + if (start == NULL) + goto err; + stop = PyLong_FromLong(r->start + r->len * r->step); + if (stop == NULL) + goto err; + step = PyLong_FromLong(r->step); + if (step == NULL) + goto err; + range = (PyObject*)make_range_object(&PyRange_Type, + start, stop, step); + if (range == NULL) + goto err; + /* return the result */ + return Py_BuildValue("N(N)i", _PyObject_GetBuiltin("iter"), range, r->index); +err: + Py_XDECREF(start); + Py_XDECREF(stop); + Py_XDECREF(step); + return NULL; +} + +static PyObject * +rangeiter_setstate(rangeiterobject *r, PyObject *state) +{ + long index = PyLong_AsLong(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0 || index >= r->len) { + PyErr_SetString(PyExc_ValueError, "index out of range"); + return NULL; + } + r->index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef rangeiter_methods[] = { {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)rangeiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)rangeiter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -1095,9 +1145,51 @@ return PyNumber_Subtract(r->len, r->index); } +static PyObject * +longrangeiter_reduce(longrangeiterobject *r) +{ + PyObject *product, *stop=NULL; + PyObject *range; + + /* create a range object for pickling. Must calculate the "stop" value */ + product = PyNumber_Multiply(r->len, r->step); + if (product == NULL) + return NULL; + stop = PyNumber_Add(r->start, product); + Py_DECREF(product); + if (stop == NULL) + return NULL; + Py_INCREF(r->start); + Py_INCREF(r->step); + range = (PyObject*)make_range_object(&PyRange_Type, + r->start, stop, r->step); + if (range == NULL) { + Py_DECREF(r->start); + Py_DECREF(stop); + Py_DECREF(r->step); + return NULL; + } + + /* return the result */ + return Py_BuildValue("N(N)O", _PyObject_GetBuiltin("iter"), range, r->index); +} + +static PyObject * +longrangeiter_setstate(longrangeiterobject *r, PyObject *state) +{ + Py_CLEAR(r->index); + r->index = state; + Py_INCREF(r->index); + Py_RETURN_NONE; +} + static PyMethodDef longrangeiter_methods[] = { {"__length_hint__", (PyCFunction)longrangeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)longrangeiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)longrangeiter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -819,8 +819,51 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject *setiter_iternext(setiterobject *si); + +static PyObject * +setiter_reduce(setiterobject *si) +{ + PyObject *list; + setiterobject tmp; + + list = PyList_New(0); + if (!list) + return NULL; + + /* copy the itertor state */ + tmp = *si; + Py_XINCREF(tmp.si_set); + + /* iterate the temporary into a list */ + for(;;) { + PyObject *element = setiter_iternext(&tmp); + if (element) { + if (PyList_Append(list, element)) { + Py_DECREF(element); + Py_DECREF(list); + Py_XDECREF(tmp.si_set); + return NULL; + } + Py_DECREF(element); + } else + break; + } + Py_XDECREF(tmp.si_set); + /* check for error */ + if (tmp.si_set != NULL) { + /* we have an error */ + Py_DECREF(list); + return NULL; + } + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + static PyMethodDef setiter_methods[] = { {"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)setiter_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -1964,8 +2007,6 @@ return result; } -PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); - static PyObject * set_sizeof(PySetObject *so) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -967,8 +967,39 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +tupleiter_reduce(tupleiterobject *it) +{ + if (it->it_seq) + return Py_BuildValue("N(O)l", _PyObject_GetBuiltin("iter"), + it->it_seq, it->it_index); + else + return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter")); +} + +static PyObject * +tupleiter_setstate(tupleiterobject *it, PyObject *state) +{ + long index = PyLong_AsLong(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (it->it_seq != NULL) { + if (index < 0) + index = 0; + else if (it->it_seq != NULL && index > PyTuple_GET_SIZE(it->it_seq)) + index = PyTuple_GET_SIZE(it->it_seq); + it->it_index = index; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef tupleiter_methods[] = { {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)tupleiter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)tupleiter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5393,9 +5393,11 @@ #if (SIZEOF_LONG == 8) # define FAST_CHAR_MASK 0x8000800080008000L # define SWAPPED_FAST_CHAR_MASK 0x0080008000800080L +# define STRIPPED_MASK 0x00FF00FF00FF00FFL #elif (SIZEOF_LONG == 4) # define FAST_CHAR_MASK 0x80008000L # define SWAPPED_FAST_CHAR_MASK 0x00800080L +# define STRIPPED_MASK 0x00FF00FFL #else # error C 'long' size should be either 4 or 8! #endif @@ -5497,7 +5499,6 @@ void *data = PyUnicode_DATA(unicode); while (_q < aligned_end) { unsigned long block = * (unsigned long *) _q; - unsigned short *pblock = (unsigned short*)█ Py_UCS4 maxch; if (native_ordering) { /* Can use buffer directly */ @@ -5506,23 +5507,22 @@ } else { /* Need to byte-swap */ - unsigned char *_p = (unsigned char*)pblock; if (block & SWAPPED_FAST_CHAR_MASK) break; - _p[0] = _q[1]; - _p[1] = _q[0]; - _p[2] = _q[3]; - _p[3] = _q[2]; -#if (SIZEOF_LONG == 8) - _p[4] = _q[5]; - _p[5] = _q[4]; - _p[6] = _q[7]; - _p[7] = _q[6]; -#endif - } - maxch = Py_MAX(pblock[0], pblock[1]); + block = ((block >> 8) & STRIPPED_MASK) | + ((block & STRIPPED_MASK) << 8); + } + maxch = (Py_UCS2)(block & 0xFFFF); #if SIZEOF_LONG == 8 - maxch = Py_MAX(maxch, Py_MAX(pblock[2], pblock[3])); + ch = (Py_UCS2)((block >> 16) & 0xFFFF); + maxch = Py_MAX(maxch, ch); + ch = (Py_UCS2)((block >> 32) & 0xFFFF); + maxch = Py_MAX(maxch, ch); + ch = (Py_UCS2)(block >> 48); + maxch = Py_MAX(maxch, ch); +#else + ch = (Py_UCS2)(block >> 16); + maxch = Py_MAX(maxch, ch); #endif if (maxch > PyUnicode_MAX_CHAR_VALUE(unicode)) { if (unicode_widen(&unicode, maxch) < 0) @@ -5530,11 +5530,24 @@ kind = PyUnicode_KIND(unicode); data = PyUnicode_DATA(unicode); } - PyUnicode_WRITE(kind, data, outpos++, pblock[0]); - PyUnicode_WRITE(kind, data, outpos++, pblock[1]); +#ifdef BYTEORDER_IS_LITTLE_ENDIAN + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block & 0xFFFF)); #if SIZEOF_LONG == 8 - PyUnicode_WRITE(kind, data, outpos++, pblock[2]); - PyUnicode_WRITE(kind, data, outpos++, pblock[3]); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 16) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 32) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 48))); +#else + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block >> 16)); +#endif +#else +#if SIZEOF_LONG == 8 + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 48))); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 32) & 0xFFFF)); + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)((block >> 16) & 0xFFFF)); +#else + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block >> 16)); +#endif + PyUnicode_WRITE(kind, data, outpos++, (Py_UCS2)(block & 0xFFFF)); #endif _q += SIZEOF_LONG; } @@ -14382,9 +14395,43 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); +static PyObject * +unicodeiter_reduce(unicodeiterobject *it) +{ + if (it->it_seq != NULL) { + return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"), + it->it_seq, it->it_index); + } else { + PyObject *u = PyUnicode_FromUnicode(NULL, 0); + if (u == NULL) + return NULL; + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), u); + } +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +unicodeiter_setstate(unicodeiterobject *it, PyObject *state) +{ + Py_ssize_t index = PyLong_AsSsize_t(state); + if (index == -1 && PyErr_Occurred()) + return NULL; + if (index < 0) + index = 0; + it->it_index = index; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + static PyMethodDef unicodeiter_methods[] = { {"__length_hint__", (PyCFunction)unicodeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)unicodeiter_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)unicodeiter_setstate, METH_O, + setstate_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -438,6 +438,19 @@ } } +static PyObject * +filter_reduce(filterobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->func, lz->it); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyMethodDef filter_methods[] = { + {"__reduce__", (PyCFunction)filter_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(filter_doc, "filter(function or None, iterable) --> filter object\n\ \n\ @@ -474,7 +487,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)filter_next, /* tp_iternext */ - 0, /* tp_methods */ + filter_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1054,6 +1067,31 @@ return result; } +static PyObject * +map_reduce(mapobject *lz) +{ + Py_ssize_t numargs = PyTuple_GET_SIZE(lz->iters); + PyObject *args = PyTuple_New(numargs+1); + Py_ssize_t i; + if (args == NULL) + return NULL; + Py_INCREF(lz->func); + PyTuple_SET_ITEM(args, 0, lz->func); + for (i = 0; iiters, i); + Py_INCREF(it); + PyTuple_SET_ITEM(args, i+1, it); + } + + return Py_BuildValue("ON", Py_TYPE(lz), args); +} + +static PyMethodDef map_methods[] = { + {"__reduce__", (PyCFunction)map_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + + PyDoc_STRVAR(map_doc, "map(func, *iterables) --> map object\n\ \n\ @@ -1090,7 +1128,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)map_next, /* tp_iternext */ - 0, /* tp_methods */ + map_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2238,6 +2276,18 @@ return result; } +static PyObject * +zip_reduce(zipobject *lz) +{ + /* Just recreate the zip with the internal iterator tuple */ + return Py_BuildValue("OO", Py_TYPE(lz), lz->ittuple); +} + +static PyMethodDef zip_methods[] = { + {"__reduce__", (PyCFunction)zip_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(zip_doc, "zip(iter1 [,iter2 [...]]) --> zip object\n\ \n\ @@ -2276,7 +2326,7 @@ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)zip_next, /* tp_iternext */ - 0, /* tp_methods */ + zip_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1356,56 +1356,67 @@ _Py_IDENTIFIER(offset); _Py_IDENTIFIER(text); + *message = NULL; + /* new style errors. `err' is an instance */ - - if (! (v = _PyObject_GetAttrId(err, &PyId_msg))) - goto finally; - *message = v; - - if (!(v = _PyObject_GetAttrId(err, &PyId_filename))) - goto finally; - if (v == Py_None) - *filename = NULL; - else if (! (*filename = _PyUnicode_AsString(v))) + *message = _PyObject_GetAttrId(err, &PyId_msg); + if (!*message) goto finally; - Py_DECREF(v); - if (!(v = _PyObject_GetAttrId(err, &PyId_lineno))) + v = _PyObject_GetAttrId(err, &PyId_filename); + if (!v) + goto finally; + if (v == Py_None) { + Py_DECREF(v); + *filename = NULL; + } + else { + *filename = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*filename) + goto finally; + } + + v = _PyObject_GetAttrId(err, &PyId_lineno); + if (!v) goto finally; hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *lineno = (int)hold; - if (!(v = _PyObject_GetAttrId(err, &PyId_offset))) + v = _PyObject_GetAttrId(err, &PyId_offset); + if (!v) goto finally; if (v == Py_None) { *offset = -1; Py_DECREF(v); - v = NULL; } else { hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *offset = (int)hold; } - if (!(v = _PyObject_GetAttrId(err, &PyId_text))) + v = _PyObject_GetAttrId(err, &PyId_text); + if (!v) goto finally; - if (v == Py_None) + if (v == Py_None) { + Py_DECREF(v); *text = NULL; - else if (!PyUnicode_Check(v) || - !(*text = _PyUnicode_AsString(v))) - goto finally; - Py_DECREF(v); + } + else { + *text = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*text) + goto finally; + } return 1; finally: - Py_XDECREF(v); + Py_XDECREF(*message); return 0; } diff --git a/Tools/scripts/abitype.py b/Tools/scripts/abitype.py --- a/Tools/scripts/abitype.py +++ b/Tools/scripts/abitype.py @@ -3,34 +3,6 @@ # Usage: abitype.py < old_code > new_code import re, sys -############ Simplistic C scanner ################################## -tokenizer = re.compile( - r"(?P#.*\n)" - r"|(?P/\*.*?\*/)" - r"|(?P[a-zA-Z_][a-zA-Z0-9_]*)" - r"|(?P[ \t\n]+)" - r"|(?P.)", - re.MULTILINE) - -tokens = [] -source = sys.stdin.read() -pos = 0 -while pos != len(source): - m = tokenizer.match(source, pos) - tokens.append([m.lastgroup, m.group()]) - pos += len(tokens[-1][1]) - if tokens[-1][0] == 'preproc': - # continuation lines are considered - # only in preprocess statements - while tokens[-1][1].endswith('\\\n'): - nl = source.find('\n', pos) - if nl == -1: - line = source[pos:] - else: - line = source[pos:nl+1] - tokens[-1][1] += line - pos += len(line) - ###### Replacement of PyTypeObject static instances ############## # classify each token, giving it a one-letter code: @@ -79,7 +51,7 @@ while tokens[pos][0] in ('ws', 'comment'): pos += 1 if tokens[pos][1] != 'PyVarObject_HEAD_INIT': - raise Exception, '%s has no PyVarObject_HEAD_INIT' % name + raise Exception('%s has no PyVarObject_HEAD_INIT' % name) while tokens[pos][1] != ')': pos += 1 pos += 1 @@ -183,18 +155,48 @@ return '\n'.join(res) -# Main loop: replace all static PyTypeObjects until -# there are none left. -while 1: - c = classify() - m = re.search('(SW)?TWIW?=W?{.*?};', c) - if not m: - break - start = m.start() - end = m.end() - name, fields = get_fields(start, m) - tokens[start:end] = [('',make_slots(name, fields))] +if __name__ == '__main__': -# Output result to stdout -for t, v in tokens: - sys.stdout.write(v) + ############ Simplistic C scanner ################################## + tokenizer = re.compile( + r"(?P#.*\n)" + r"|(?P/\*.*?\*/)" + r"|(?P[a-zA-Z_][a-zA-Z0-9_]*)" + r"|(?P[ \t\n]+)" + r"|(?P.)", + re.MULTILINE) + + tokens = [] + source = sys.stdin.read() + pos = 0 + while pos != len(source): + m = tokenizer.match(source, pos) + tokens.append([m.lastgroup, m.group()]) + pos += len(tokens[-1][1]) + if tokens[-1][0] == 'preproc': + # continuation lines are considered + # only in preprocess statements + while tokens[-1][1].endswith('\\\n'): + nl = source.find('\n', pos) + if nl == -1: + line = source[pos:] + else: + line = source[pos:nl+1] + tokens[-1][1] += line + pos += len(line) + + # Main loop: replace all static PyTypeObjects until + # there are none left. + while 1: + c = classify() + m = re.search('(SW)?TWIW?=W?{.*?};', c) + if not m: + break + start = m.start() + end = m.end() + name, fields = get_fields(start, m) + tokens[start:end] = [('',make_slots(name, fields))] + + # Output result to stdout + for t, v in tokens: + sys.stdout.write(v) diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py --- a/Tools/scripts/find_recursionlimit.py +++ b/Tools/scripts/find_recursionlimit.py @@ -106,14 +106,16 @@ else: print("Yikes!") -limit = 1000 -while 1: - check_limit(limit, "test_recurse") - check_limit(limit, "test_add") - check_limit(limit, "test_repr") - check_limit(limit, "test_init") - check_limit(limit, "test_getattr") - check_limit(limit, "test_getitem") - check_limit(limit, "test_cpickle") - print("Limit of %d is fine" % limit) - limit = limit + 100 +if __name__ == '__main__': + + limit = 1000 + while 1: + check_limit(limit, "test_recurse") + check_limit(limit, "test_add") + check_limit(limit, "test_repr") + check_limit(limit, "test_init") + check_limit(limit, "test_getattr") + check_limit(limit, "test_getitem") + check_limit(limit, "test_cpickle") + print("Limit of %d is fine" % limit) + limit = limit + 100 diff --git a/Tools/scripts/findnocoding.py b/Tools/scripts/findnocoding.py --- a/Tools/scripts/findnocoding.py +++ b/Tools/scripts/findnocoding.py @@ -76,29 +76,31 @@ -c: recognize Python source files trying to compile them -d: debug output""" % sys.argv[0] -try: - opts, args = getopt.getopt(sys.argv[1:], 'cd') -except getopt.error as msg: - print(msg, file=sys.stderr) - print(usage, file=sys.stderr) - sys.exit(1) +if __name__ == '__main__': -is_python = pysource.looks_like_python -debug = False + try: + opts, args = getopt.getopt(sys.argv[1:], 'cd') + except getopt.error as msg: + print(msg, file=sys.stderr) + print(usage, file=sys.stderr) + sys.exit(1) -for o, a in opts: - if o == '-c': - is_python = pysource.can_be_compiled - elif o == '-d': - debug = True + is_python = pysource.looks_like_python + debug = False -if not args: - print(usage, file=sys.stderr) - sys.exit(1) + for o, a in opts: + if o == '-c': + is_python = pysource.can_be_compiled + elif o == '-d': + debug = True -for fullpath in pysource.walk_python_files(args, is_python): - if debug: - print("Testing for coding: %s" % fullpath) - result = needs_declaration(fullpath) - if result: - print(fullpath) + if not args: + print(usage, file=sys.stderr) + sys.exit(1) + + for fullpath in pysource.walk_python_files(args, is_python): + if debug: + print("Testing for coding: %s" % fullpath) + result = needs_declaration(fullpath) + if result: + print(fullpath) diff --git a/Tools/scripts/fixcid.py b/Tools/scripts/fixcid.py --- a/Tools/scripts/fixcid.py +++ b/Tools/scripts/fixcid.py @@ -292,7 +292,7 @@ if not words: continue if len(words) == 3 and words[0] == 'struct': words[:2] = [words[0] + ' ' + words[1]] - elif len(words) <> 2: + elif len(words) != 2: err(substfile + '%s:%r: warning: bad line: %r' % (substfile, lineno, line)) continue if Reverse: diff --git a/Tools/scripts/md5sum.py b/Tools/scripts/md5sum.py --- a/Tools/scripts/md5sum.py +++ b/Tools/scripts/md5sum.py @@ -20,7 +20,7 @@ import sys import os import getopt -import md5 +from hashlib import md5 def sum(*files): sts = 0 diff --git a/Tools/scripts/parseentities.py b/Tools/scripts/parseentities.py --- a/Tools/scripts/parseentities.py +++ b/Tools/scripts/parseentities.py @@ -13,7 +13,6 @@ """ import re,sys -import TextTools entityRE = re.compile('') @@ -45,7 +44,7 @@ charcode = repr(charcode) else: charcode = repr(charcode) - comment = TextTools.collapse(comment) + comment = ' '.join(comment.split()) f.write(" '%s':\t%s, \t# %s\n" % (name,charcode,comment)) f.write('\n}\n') diff --git a/Tools/scripts/pdeps.py b/Tools/scripts/pdeps.py --- a/Tools/scripts/pdeps.py +++ b/Tools/scripts/pdeps.py @@ -76,10 +76,9 @@ nextline = fp.readline() if not nextline: break line = line[:-1] + nextline - if m_import.match(line) >= 0: - (a, b), (a1, b1) = m_import.regs[:2] - elif m_from.match(line) >= 0: - (a, b), (a1, b1) = m_from.regs[:2] + m_found = m_import.match(line) or m_from.match(line) + if m_found: + (a, b), (a1, b1) = m_found.regs[:2] else: continue words = line[a1:b1].split(',') # print '#', line, words @@ -87,6 +86,7 @@ word = word.strip() if word not in list: list.append(word) + fp.close() # Compute closure (this is in fact totally general) @@ -123,7 +123,7 @@ def inverse(table): inv = {} for key in table.keys(): - if not inv.has_key(key): + if key not in inv: inv[key] = [] for item in table[key]: store(inv, item, key) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:13:26 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 06 Apr 2012 19:13:26 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314500=3A_Fix_impor?= =?utf8?q?tlib=2Etest=2Eimport=5F=2Etest=5Fpackages_to_clean_up?= Message-ID: http://hg.python.org/cpython/rev/1c3bd0cc3eca changeset: 76140:1c3bd0cc3eca user: Brett Cannon date: Fri Apr 06 13:13:08 2012 -0400 summary: Issue #14500: Fix importlib.test.import_.test_packages to clean up after itself properly. files: Lib/importlib/test/import_/test_packages.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/importlib/test/import_/test_packages.py b/Lib/importlib/test/import_/test_packages.py --- a/Lib/importlib/test/import_/test_packages.py +++ b/Lib/importlib/test/import_/test_packages.py @@ -3,6 +3,7 @@ import sys import unittest import importlib +from test import support class ParentModuleTests(unittest.TestCase): @@ -38,7 +39,10 @@ module_code={'mod': module_injection}) with mock_modules as mock: with util.import_state(meta_path=[mock]): - submodule = import_util.import_(subname) + try: + submodule = import_util.import_(subname) + finally: + support.unload(subname) def test_main(): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:21:05 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 19:21:05 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4xKTogYnVtcCB0byAzLjEu?= =?utf8?q?5_final?= Message-ID: http://hg.python.org/cpython/rev/7395330e495e changeset: 76141:7395330e495e branch: 3.1 tag: v3.1.5 parent: 75708:44eba26951f6 user: Benjamin Peterson date: Fri Apr 06 13:17:25 2012 -0400 summary: bump to 3.1.5 final files: Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 2 +- Misc/RPM/python-3.1.spec | 2 +- 5 files changed, 7 insertions(+), 7 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 1 #define PY_MICRO_VERSION 5 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.1.5rc2" +#define PY_VERSION "3.1.5" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.1.5rc2" +__version__ = "3.1.5" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.1.5rc2" +IDLE_VERSION = "3.1.5" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,7 +5,7 @@ What's New in Python 3.1.5? =========================== -*Release date: 2012-02-23* +*Release date: 2012-04-08* Core and Builtins ----------------- diff --git a/Misc/RPM/python-3.1.spec b/Misc/RPM/python-3.1.spec --- a/Misc/RPM/python-3.1.spec +++ b/Misc/RPM/python-3.1.spec @@ -34,7 +34,7 @@ %define name python #--start constants-- -%define version 3.1.5rc2 +%define version 3.1.5 %define libvers 3.1 #--end constants-- %define release 1pydotorg -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:21:06 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 19:21:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E1=29=3A_Added_tag_v3=2E?= =?utf8?q?1=2E5_for_changeset_7395330e495e?= Message-ID: http://hg.python.org/cpython/rev/f1876c0a630a changeset: 76142:f1876c0a630a branch: 3.1 user: Benjamin Peterson date: Fri Apr 06 13:17:30 2012 -0400 summary: Added tag v3.1.5 for changeset 7395330e495e files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -79,3 +79,4 @@ c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4 ee26aca3219cf4bb0b93352e83edcc9cb28c7802 v3.1.5rc1 75db2bc69fc9a3e4801e94e3e19801cb096208d8 v3.1.5rc2 +7395330e495ec3316862ca1f6ce0aaf7bdf6785b v3.1.5 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:21:07 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 19:21:07 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4xIC0+IDMuMik6?= =?utf8?q?_merge_3=2E1?= Message-ID: http://hg.python.org/cpython/rev/2d8edb8ea89b changeset: 76143:2d8edb8ea89b branch: 3.2 parent: 76084:43606a4085b0 parent: 76142:f1876c0a630a user: Benjamin Peterson date: Fri Apr 06 13:19:52 2012 -0400 summary: merge 3.1 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -78,6 +78,7 @@ 32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1 c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4 ee26aca3219cf4bb0b93352e83edcc9cb28c7802 v3.1.5rc1 +7395330e495ec3316862ca1f6ce0aaf7bdf6785b v3.1.5 b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1 56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2 da012d9a2c23d144e399d2e01a55b8a83ad94573 v3.2a3 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:21:08 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 19:21:08 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogcG9ydCAzLjEuNXJj?= =?utf8?q?2_tag?= Message-ID: http://hg.python.org/cpython/rev/6020f4d20f99 changeset: 76144:6020f4d20f99 branch: 3.2 user: Benjamin Peterson date: Fri Apr 06 13:20:01 2012 -0400 summary: port 3.1.5rc2 tag files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -78,6 +78,7 @@ 32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1 c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4 ee26aca3219cf4bb0b93352e83edcc9cb28c7802 v3.1.5rc1 +75db2bc69fc9a3e4801e94e3e19801cb096208d8 v3.1.5rc2 7395330e495ec3316862ca1f6ce0aaf7bdf6785b v3.1.5 b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1 56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:21:08 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 19:21:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/a0a4b99182ad changeset: 76145:a0a4b99182ad parent: 76139:fbbb14604e94 parent: 76144:6020f4d20f99 user: Benjamin Peterson date: Fri Apr 06 13:20:16 2012 -0400 summary: merge 3.2 files: .hgtags | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -78,6 +78,8 @@ 32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1 c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4 ee26aca3219cf4bb0b93352e83edcc9cb28c7802 v3.1.5rc1 +75db2bc69fc9a3e4801e94e3e19801cb096208d8 v3.1.5rc2 +7395330e495ec3316862ca1f6ce0aaf7bdf6785b v3.1.5 b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1 56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2 da012d9a2c23d144e399d2e01a55b8a83ad94573 v3.2a3 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:21:09 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 19:21:09 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/7e041dd3f496 changeset: 76146:7e041dd3f496 parent: 76145:a0a4b99182ad parent: 76140:1c3bd0cc3eca user: Benjamin Peterson date: Fri Apr 06 13:20:25 2012 -0400 summary: merge heads files: Lib/importlib/test/import_/test_packages.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/importlib/test/import_/test_packages.py b/Lib/importlib/test/import_/test_packages.py --- a/Lib/importlib/test/import_/test_packages.py +++ b/Lib/importlib/test/import_/test_packages.py @@ -3,6 +3,7 @@ import sys import unittest import importlib +from test import support class ParentModuleTests(unittest.TestCase): @@ -38,7 +39,10 @@ module_code={'mod': module_injection}) with mock_modules as mock: with util.import_state(meta_path=[mock]): - submodule = import_util.import_(subname) + try: + submodule = import_util.import_(subname) + finally: + support.unload(subname) def test_main(): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:21:10 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 19:21:10 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMik6?= =?utf8?q?_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/5b68fd4246fc changeset: 76147:5b68fd4246fc branch: 3.2 parent: 76144:6020f4d20f99 parent: 76134:e9b8115c5b25 user: Benjamin Peterson date: Fri Apr 06 13:20:39 2012 -0400 summary: merge heads files: Doc/library/subprocess.rst | 2 +- Doc/library/threading.rst | 2 +- Lib/idlelib/tabbedpages.py | 4 +- Lib/multiprocessing/connection.py | 4 + Lib/test/test_multiprocessing.py | 6 + Lib/test/test_tools.py | 73 ++++++++++++- Lib/tkinter/ttk.py | 2 +- Misc/NEWS | 7 + Tools/scripts/abitype.py | 88 ++++++++------- Tools/scripts/find_recursionlimit.py | 24 ++-- Tools/scripts/findnocoding.py | 46 ++++---- Tools/scripts/fixcid.py | 2 +- Tools/scripts/md5sum.py | 2 +- Tools/scripts/parseentities.py | 3 +- Tools/scripts/pdeps.py | 10 +- 15 files changed, 183 insertions(+), 92 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -735,7 +735,7 @@ to receive a SIGPIPE if p2 exits before p1. Alternatively, for trusted input, the shell's own pipeline support may still -be used directly: +be used directly:: output=`dmesg | grep hda` # becomes diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -430,7 +430,7 @@ are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed. - Do not call this method when the lock is unlocked. + When invoked on an unlocked lock, a :exc:`ThreadError` is raised. There is no return value. diff --git a/Lib/idlelib/tabbedpages.py b/Lib/idlelib/tabbedpages.py --- a/Lib/idlelib/tabbedpages.py +++ b/Lib/idlelib/tabbedpages.py @@ -78,7 +78,7 @@ def remove_tab(self, tab_name): """Remove the tab named """ if not tab_name in self._tab_names: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) self._tab_names.remove(tab_name) self._arrange_tabs() @@ -88,7 +88,7 @@ if tab_name == self._selected_tab: return if tab_name is not None and tab_name not in self._tabs: - raise KeyError("No such Tab: '%s" % page_name) + raise KeyError("No such Tab: '%s" % tab_name) # deselect the current selected tab if self._selected_tab is not None: diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -101,6 +101,10 @@ if sys.platform != 'win32' and family == 'AF_PIPE': raise ValueError('Family %s is not recognized.' % family) + if sys.platform == 'win32' and family == 'AF_UNIX': + # double check + if not hasattr(socket, family): + raise ValueError('Family %s is not recognized.' % family) def address_type(address): ''' diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2331,6 +2331,12 @@ with self.assertRaises(ValueError): multiprocessing.connection.Listener(r'\\.\test') + @unittest.skipUnless(WIN32, "skipped on non-Windows platforms") + def test_invalid_family_win32(self): + with self.assertRaises(ValueError): + multiprocessing.connection.Listener('/var/test.pipe') + + testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, TestStdinBadfiledescriptor, TestInvalidFamily] diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -5,8 +5,11 @@ """ import os +import sys +import imp import unittest import sysconfig +import tempfile from test import support from test.script_helper import assert_python_ok @@ -17,10 +20,11 @@ srcdir = sysconfig.get_config_var('projectbase') basepath = os.path.join(os.getcwd(), srcdir, 'Tools') +scriptsdir = os.path.join(basepath, 'scripts') class ReindentTests(unittest.TestCase): - script = os.path.join(basepath, 'scripts', 'reindent.py') + script = os.path.join(scriptsdir, 'reindent.py') def test_noargs(self): assert_python_ok(self.script) @@ -31,8 +35,73 @@ self.assertGreater(err, b'') +class TestSundryScripts(unittest.TestCase): + # At least make sure the rest don't have syntax errors. When tests are + # added for a script it should be added to the whitelist below. + + # scripts that have independent tests. + whitelist = ['reindent.py'] + # scripts that can't be imported without running + blacklist = ['make_ctype.py'] + # scripts that use windows-only modules + windows_only = ['win_add2path.py'] + # blacklisted for other reasons + other = ['analyze_dxp.py'] + + skiplist = blacklist + whitelist + windows_only + other + + def setUp(self): + cm = support.DirsOnSysPath(scriptsdir) + cm.__enter__() + self.addCleanup(cm.__exit__) + + def test_sundry(self): + for fn in os.listdir(scriptsdir): + if fn.endswith('.py') and fn not in self.skiplist: + __import__(fn[:-3]) + + @unittest.skipIf(sys.platform != "win32", "Windows-only test") + def test_sundry_windows(self): + for fn in self.windows_only: + __import__(fn[:-3]) + + @unittest.skipIf(not support.threading, "test requires _thread module") + def test_analyze_dxp_import(self): + if hasattr(sys, 'getdxp'): + import analyze_dxp + else: + with self.assertRaises(RuntimeError): + import analyze_dxp + + +class PdepsTests(unittest.TestCase): + + @classmethod + def setUpClass(self): + path = os.path.join(scriptsdir, 'pdeps.py') + self.pdeps = imp.load_source('pdeps', path) + + @classmethod + def tearDownClass(self): + if 'pdeps' in sys.modules: + del sys.modules['pdeps'] + + def test_process_errors(self): + # Issue #14492: m_import.match(line) can be None. + with tempfile.TemporaryDirectory() as tmpdir: + fn = os.path.join(tmpdir, 'foo') + with open(fn, 'w') as stream: + stream.write("#!/this/will/fail") + self.pdeps.process(fn, {}) + + def test_inverse_attribute_error(self): + # Issue #14492: this used to fail with an AttributeError. + self.pdeps.inverse({'a': []}) + + def test_main(): - support.run_unittest(ReindentTests) + support.run_unittest(*[obj for obj in globals().values() + if isinstance(obj, type)]) if __name__ == '__main__': diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -1253,7 +1253,7 @@ def exists(self, item): - """Returns True if the specified item is present in the three, + """Returns True if the specified item is present in the tree, False otherwise.""" return bool(self.tk.call(self._w, "exists", item)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,13 @@ Library ------- +- Issue #14496: Fix wrong name in idlelib/tabbedpages.py. + Patch by Popa Claudiu. + +- Issue #14482: Raise a ValueError, not a NameError, when trying to create + a multiprocessing Client or Listener with an AF_UNIX type address under + Windows. Patch by Popa Claudiu. + - Issue #14151: Raise a ValueError, not a NameError, when trying to create a multiprocessing Client or Listener with an AF_PIPE type address under non-Windows platforms. Patch by Popa Claudiu. diff --git a/Tools/scripts/abitype.py b/Tools/scripts/abitype.py --- a/Tools/scripts/abitype.py +++ b/Tools/scripts/abitype.py @@ -3,34 +3,6 @@ # Usage: abitype.py < old_code > new_code import re, sys -############ Simplistic C scanner ################################## -tokenizer = re.compile( - r"(?P#.*\n)" - r"|(?P/\*.*?\*/)" - r"|(?P[a-zA-Z_][a-zA-Z0-9_]*)" - r"|(?P[ \t\n]+)" - r"|(?P.)", - re.MULTILINE) - -tokens = [] -source = sys.stdin.read() -pos = 0 -while pos != len(source): - m = tokenizer.match(source, pos) - tokens.append([m.lastgroup, m.group()]) - pos += len(tokens[-1][1]) - if tokens[-1][0] == 'preproc': - # continuation lines are considered - # only in preprocess statements - while tokens[-1][1].endswith('\\\n'): - nl = source.find('\n', pos) - if nl == -1: - line = source[pos:] - else: - line = source[pos:nl+1] - tokens[-1][1] += line - pos += len(line) - ###### Replacement of PyTypeObject static instances ############## # classify each token, giving it a one-letter code: @@ -79,7 +51,7 @@ while tokens[pos][0] in ('ws', 'comment'): pos += 1 if tokens[pos][1] != 'PyVarObject_HEAD_INIT': - raise Exception, '%s has no PyVarObject_HEAD_INIT' % name + raise Exception('%s has no PyVarObject_HEAD_INIT' % name) while tokens[pos][1] != ')': pos += 1 pos += 1 @@ -183,18 +155,48 @@ return '\n'.join(res) -# Main loop: replace all static PyTypeObjects until -# there are none left. -while 1: - c = classify() - m = re.search('(SW)?TWIW?=W?{.*?};', c) - if not m: - break - start = m.start() - end = m.end() - name, fields = get_fields(start, m) - tokens[start:end] = [('',make_slots(name, fields))] +if __name__ == '__main__': -# Output result to stdout -for t, v in tokens: - sys.stdout.write(v) + ############ Simplistic C scanner ################################## + tokenizer = re.compile( + r"(?P#.*\n)" + r"|(?P/\*.*?\*/)" + r"|(?P[a-zA-Z_][a-zA-Z0-9_]*)" + r"|(?P[ \t\n]+)" + r"|(?P.)", + re.MULTILINE) + + tokens = [] + source = sys.stdin.read() + pos = 0 + while pos != len(source): + m = tokenizer.match(source, pos) + tokens.append([m.lastgroup, m.group()]) + pos += len(tokens[-1][1]) + if tokens[-1][0] == 'preproc': + # continuation lines are considered + # only in preprocess statements + while tokens[-1][1].endswith('\\\n'): + nl = source.find('\n', pos) + if nl == -1: + line = source[pos:] + else: + line = source[pos:nl+1] + tokens[-1][1] += line + pos += len(line) + + # Main loop: replace all static PyTypeObjects until + # there are none left. + while 1: + c = classify() + m = re.search('(SW)?TWIW?=W?{.*?};', c) + if not m: + break + start = m.start() + end = m.end() + name, fields = get_fields(start, m) + tokens[start:end] = [('',make_slots(name, fields))] + + # Output result to stdout + for t, v in tokens: + sys.stdout.write(v) diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py --- a/Tools/scripts/find_recursionlimit.py +++ b/Tools/scripts/find_recursionlimit.py @@ -106,14 +106,16 @@ else: print("Yikes!") -limit = 1000 -while 1: - check_limit(limit, "test_recurse") - check_limit(limit, "test_add") - check_limit(limit, "test_repr") - check_limit(limit, "test_init") - check_limit(limit, "test_getattr") - check_limit(limit, "test_getitem") - check_limit(limit, "test_cpickle") - print("Limit of %d is fine" % limit) - limit = limit + 100 +if __name__ == '__main__': + + limit = 1000 + while 1: + check_limit(limit, "test_recurse") + check_limit(limit, "test_add") + check_limit(limit, "test_repr") + check_limit(limit, "test_init") + check_limit(limit, "test_getattr") + check_limit(limit, "test_getitem") + check_limit(limit, "test_cpickle") + print("Limit of %d is fine" % limit) + limit = limit + 100 diff --git a/Tools/scripts/findnocoding.py b/Tools/scripts/findnocoding.py --- a/Tools/scripts/findnocoding.py +++ b/Tools/scripts/findnocoding.py @@ -76,29 +76,31 @@ -c: recognize Python source files trying to compile them -d: debug output""" % sys.argv[0] -try: - opts, args = getopt.getopt(sys.argv[1:], 'cd') -except getopt.error as msg: - print(msg, file=sys.stderr) - print(usage, file=sys.stderr) - sys.exit(1) +if __name__ == '__main__': -is_python = pysource.looks_like_python -debug = False + try: + opts, args = getopt.getopt(sys.argv[1:], 'cd') + except getopt.error as msg: + print(msg, file=sys.stderr) + print(usage, file=sys.stderr) + sys.exit(1) -for o, a in opts: - if o == '-c': - is_python = pysource.can_be_compiled - elif o == '-d': - debug = True + is_python = pysource.looks_like_python + debug = False -if not args: - print(usage, file=sys.stderr) - sys.exit(1) + for o, a in opts: + if o == '-c': + is_python = pysource.can_be_compiled + elif o == '-d': + debug = True -for fullpath in pysource.walk_python_files(args, is_python): - if debug: - print("Testing for coding: %s" % fullpath) - result = needs_declaration(fullpath) - if result: - print(fullpath) + if not args: + print(usage, file=sys.stderr) + sys.exit(1) + + for fullpath in pysource.walk_python_files(args, is_python): + if debug: + print("Testing for coding: %s" % fullpath) + result = needs_declaration(fullpath) + if result: + print(fullpath) diff --git a/Tools/scripts/fixcid.py b/Tools/scripts/fixcid.py --- a/Tools/scripts/fixcid.py +++ b/Tools/scripts/fixcid.py @@ -292,7 +292,7 @@ if not words: continue if len(words) == 3 and words[0] == 'struct': words[:2] = [words[0] + ' ' + words[1]] - elif len(words) <> 2: + elif len(words) != 2: err(substfile + '%s:%r: warning: bad line: %r' % (substfile, lineno, line)) continue if Reverse: diff --git a/Tools/scripts/md5sum.py b/Tools/scripts/md5sum.py --- a/Tools/scripts/md5sum.py +++ b/Tools/scripts/md5sum.py @@ -20,7 +20,7 @@ import sys import os import getopt -import md5 +from hashlib import md5 def sum(*files): sts = 0 diff --git a/Tools/scripts/parseentities.py b/Tools/scripts/parseentities.py --- a/Tools/scripts/parseentities.py +++ b/Tools/scripts/parseentities.py @@ -13,7 +13,6 @@ """ import re,sys -import TextTools entityRE = re.compile('') @@ -45,7 +44,7 @@ charcode = repr(charcode) else: charcode = repr(charcode) - comment = TextTools.collapse(comment) + comment = ' '.join(comment.split()) f.write(" '%s':\t%s, \t# %s\n" % (name,charcode,comment)) f.write('\n}\n') diff --git a/Tools/scripts/pdeps.py b/Tools/scripts/pdeps.py --- a/Tools/scripts/pdeps.py +++ b/Tools/scripts/pdeps.py @@ -76,10 +76,9 @@ nextline = fp.readline() if not nextline: break line = line[:-1] + nextline - if m_import.match(line) >= 0: - (a, b), (a1, b1) = m_import.regs[:2] - elif m_from.match(line) >= 0: - (a, b), (a1, b1) = m_from.regs[:2] + m_found = m_import.match(line) or m_from.match(line) + if m_found: + (a, b), (a1, b1) = m_found.regs[:2] else: continue words = line[a1:b1].split(',') # print '#', line, words @@ -87,6 +86,7 @@ word = word.strip() if word not in list: list.append(word) + fp.close() # Compute closure (this is in fact totally general) @@ -123,7 +123,7 @@ def inverse(table): inv = {} for key in table.keys(): - if not inv.has_key(key): + if key not in inv: inv[key] = [] for item in table[key]: store(inv, item, key) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 6 19:21:11 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 06 Apr 2012 19:21:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/388016438a50 changeset: 76148:388016438a50 parent: 76146:7e041dd3f496 parent: 76147:5b68fd4246fc user: Benjamin Peterson date: Fri Apr 06 13:20:49 2012 -0400 summary: merge 3.2 files: -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Apr 7 05:35:32 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 07 Apr 2012 05:35:32 +0200 Subject: [Python-checkins] Daily reference leaks (388016438a50): sum=0 Message-ID: results for 388016438a50 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogOgEgRq', '-x'] From python-checkins at python.org Sat Apr 7 07:12:21 2012 From: python-checkins at python.org (ross.lagerwall) Date: Sat, 07 Apr 2012 07:12:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Don=27t_Py=5FDECREF_NULL_va?= =?utf8?q?riable_in_io=2EIncrementalNewlineDecoder=2E?= Message-ID: http://hg.python.org/cpython/rev/7657a229d513 changeset: 76149:7657a229d513 user: Ross Lagerwall date: Sat Apr 07 07:09:57 2012 +0200 summary: Don't Py_DECREF NULL variable in io.IncrementalNewlineDecoder. Found with Clang's Static Analyzer. files: Misc/NEWS | 2 ++ Modules/_io/textio.c | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,8 @@ Library ------- +- Don't Py_DECREF NULL variable in io.IncrementalNewlineDecoder. + - Issue #8515: Set __file__ when run file in IDLE. Initial patch by Bruce Frederiksen. diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -460,7 +460,7 @@ output = PyUnicode_FromKindAndData(kind, translated, out); PyMem_Free(translated); if (!output) - goto error; + return NULL; } self->seennl |= seennl; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 13:24:49 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Sat, 07 Apr 2012 13:24:49 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314310=3A_inter-pro?= =?utf8?q?cess_socket_duplication_for_windows?= Message-ID: http://hg.python.org/cpython/rev/51b4bddd0e92 changeset: 76150:51b4bddd0e92 user: Kristj?n Valur J?nsson date: Sat Apr 07 11:23:31 2012 +0000 summary: Issue #14310: inter-process socket duplication for windows files: Doc/library/socket.rst | 25 ++++++ Lib/socket.py | 10 ++- Lib/test/test_socket.py | 105 ++++++++++++++++++++++++++++ Misc/NEWS | 3 + Modules/socketmodule.c | 73 +++++++++++++++++- 5 files changed, 208 insertions(+), 8 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -680,6 +680,16 @@ .. versionadded:: 3.3 +.. function:: fromshare(data) + + Instantiate a socket from data obtained from :meth:`~socket.share`. + The socket is assumed to be in blocking mode. + + Availability: Windows. + + .. versionadded:: 3.3 + + .. data:: SocketType This is a Python type object that represents the socket object type. It is the @@ -1082,6 +1092,21 @@ are disallowed. If *how* is :const:`SHUT_RDWR`, further sends and receives are disallowed. + +.. method:: socket.share(process_id) + + :platform: Windows + + Duplacet a socket and prepare it for sharing with a target process. The + target process must be provided with *process_id*. The resulting bytes object + can then be passed to the target process using some form of interprocess + communication and the socket can be recreated there using :func:`fromshare`. + Once this method has been called, it is safe to close the socket since + the operating system has already duplicated it for the target process. + + .. versionadded:: 3.3 + + Note that there are no methods :meth:`read` or :meth:`write`; use :meth:`~socket.recv` and :meth:`~socket.send` without *flags* argument instead. diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -12,6 +12,7 @@ socket() -- create a new socket object socketpair() -- create a pair of new socket objects [*] fromfd() -- create a socket object from an open file descriptor [*] +fromshare() -- create a socket object from data received from socket.share() [*] gethostname() -- return the current hostname gethostbyname() -- map a hostname to its IP number gethostbyaddr() -- map an IP number or hostname to DNS info @@ -209,7 +210,6 @@ self._closed = True return super().detach() - def fromfd(fd, family, type, proto=0): """ fromfd(fd, family, type[, proto]) -> socket object @@ -219,6 +219,14 @@ nfd = dup(fd) return socket(family, type, proto, nfd) +if hasattr(_socket.socket, "share"): + def fromshare(info): + """ fromshare(info) -> socket object + + Create a socket object from a the bytes object returned by + socket.share(pid). + """ + return socket(0, 0, 0, info) if hasattr(_socket, "socketpair"): 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 @@ -26,6 +26,10 @@ import fcntl except ImportError: fcntl = False +try: + import multiprocessing +except ImportError: + multiprocessing = False HOST = support.HOST MSG = 'Michael Gilfix was here\u1234\r\n'.encode('utf-8') ## test unicode string and carriage return @@ -4643,6 +4647,106 @@ socket.setdefaulttimeout(t) + at unittest.skipUnless(os.name == "nt", "Windows specific") + at unittest.skipUnless(multiprocessing, "need multiprocessing") +class TestSocketSharing(SocketTCPTest): + # This must be classmethod and not staticmethod or multiprocessing + # won't be able to bootstrap it. + @classmethod + def remoteProcessServer(cls, q): + # Recreate socket from shared data + sdata = q.get() + message = q.get() + + s = socket.fromshare(sdata) + s2, c = s.accept() + + # Send the message + s2.sendall(message) + s2.close() + s.close() + + def testShare(self): + # Transfer the listening server socket to another process + # and service it from there. + + # Create process: + q = multiprocessing.Queue() + p = multiprocessing.Process(target=self.remoteProcessServer, args=(q,)) + p.start() + + # Get the shared socket data + data = self.serv.share(p.pid) + + # Pass the shared socket to the other process + addr = self.serv.getsockname() + self.serv.close() + q.put(data) + + # The data that the server will send us + message = b"slapmahfro" + q.put(message) + + # Connect + s = socket.create_connection(addr) + # listen for the data + m = [] + while True: + data = s.recv(100) + if not data: + break + m.append(data) + s.close() + received = b"".join(m) + self.assertEqual(received, message) + p.join() + + def testShareLength(self): + data = self.serv.share(os.getpid()) + self.assertRaises(ValueError, socket.fromshare, data[:-1]) + self.assertRaises(ValueError, socket.fromshare, data+b"foo") + + def compareSockets(self, org, other): + # socket sharing is expected to work only for blocking socket + # since the internal python timout value isn't transfered. + self.assertEqual(org.gettimeout(), None) + self.assertEqual(org.gettimeout(), other.gettimeout()) + + self.assertEqual(org.family, other.family) + self.assertEqual(org.type, other.type) + # If the user specified "0" for proto, then + # internally windows will have picked the correct value. + # Python introspection on the socket however will still return + # 0. For the shared socket, the python value is recreated + # from the actual value, so it may not compare correctly. + if org.proto != 0: + self.assertEqual(org.proto, other.proto) + + def testShareLocal(self): + data = self.serv.share(os.getpid()) + s = socket.fromshare(data) + try: + self.compareSockets(self.serv, s) + finally: + s.close() + + def testTypes(self): + families = [socket.AF_INET, socket.AF_INET6] + types = [socket.SOCK_STREAM, socket.SOCK_DGRAM] + for f in families: + for t in types: + source = socket.socket(f, t) + try: + data = source.share(os.getpid()) + shared = socket.fromshare(data) + try: + self.compareSockets(source, shared) + finally: + shared.close() + finally: + source.close() + + def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, TestExceptions, BufferIOTest, BasicTCPTest2, BasicUDPTest, UDPTimeoutTest ] @@ -4699,6 +4803,7 @@ # These are slow when setitimer() is not available InterruptedRecvTimeoutTest, InterruptedSendTimeoutTest, + TestSocketSharing, ]) thread_info = support.threading_setup() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -232,6 +232,9 @@ - Issue #14210: pdb now has tab-completion not only for command names, but also for their arguments, wherever possible. +- Issue #14310: Sockets can now be with other processes on Windows using + the api socket.socket.share() and socket.fromshare(). + Build ----- diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3771,6 +3771,34 @@ Control the socket with WSAIoctl syscall. Currently supported 'cmd' values are\n\ SIO_RCVALL: 'option' must be one of the socket.RCVALL_* constants.\n\ SIO_KEEPALIVE_VALS: 'option' is a tuple of (onoff, timeout, interval)."); +#endif + +#if defined(MS_WINDOWS) +static PyObject* +sock_share(PySocketSockObject *s, PyObject *arg) +{ + WSAPROTOCOL_INFO info; + DWORD processId; + int result; + + if (!PyArg_ParseTuple(arg, "I", &processId)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = WSADuplicateSocket(s->sock_fd, processId, &info); + Py_END_ALLOW_THREADS + if (result == SOCKET_ERROR) + return set_error(); + return PyBytes_FromStringAndSize((const char*)&info, sizeof(info)); +} +PyDoc_STRVAR(sock_share_doc, +"share(process_id) -> bytes\n\ +\n\ +Share the socket with another process. The target process id\n\ +must be provided and the resulting bytes object passed to the target\n\ +process. There the shared socket can be instantiated by calling\n\ +socket.fromshare()."); + #endif @@ -3803,6 +3831,10 @@ {"ioctl", (PyCFunction)sock_ioctl, METH_VARARGS, sock_ioctl_doc}, #endif +#if defined(MS_WINDOWS) + {"share", (PyCFunction)sock_share, METH_VARARGS, + sock_share_doc}, +#endif {"listen", (PyCFunction)sock_listen, METH_O, listen_doc}, {"recv", (PyCFunction)sock_recv, METH_VARARGS, @@ -3930,13 +3962,40 @@ return -1; if (fdobj != NULL && fdobj != Py_None) { - fd = PyLong_AsSocket_t(fdobj); - if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) - return -1; - if (fd == INVALID_SOCKET) { - PyErr_SetString(PyExc_ValueError, - "can't use invalid socket value"); - return -1; +#ifdef MS_WINDOWS + /* recreate a socket that was duplicated */ + if (PyBytes_Check(fdobj)) { + WSAPROTOCOL_INFO info; + if (PyBytes_GET_SIZE(fdobj) != sizeof(info)) { + PyErr_Format(PyExc_ValueError, + "socket descriptor string has wrong size, " + "should be %zu bytes.", sizeof(info)); + return -1; + } + memcpy(&info, PyBytes_AS_STRING(fdobj), sizeof(info)); + Py_BEGIN_ALLOW_THREADS + fd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, &info, 0, WSA_FLAG_OVERLAPPED); + Py_END_ALLOW_THREADS + if (fd == INVALID_SOCKET) { + set_error(); + return -1; + } + family = info.iAddressFamily; + type = info.iSocketType; + proto = info.iProtocol; + } + else +#endif + { + fd = PyLong_AsSocket_t(fdobj); + if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) + return -1; + if (fd == INVALID_SOCKET) { + PyErr_SetString(PyExc_ValueError, + "can't use invalid socket value"); + return -1; + } } } else { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 16:12:25 2012 From: python-checkins at python.org (stefan.krah) Date: Sat, 07 Apr 2012 16:12:25 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_1=29_Fix_comment=2E?= Message-ID: http://hg.python.org/cpython/rev/a80a579282c7 changeset: 76151:a80a579282c7 parent: 76132:ec3e0f1a3b8d user: Stefan Krah date: Sat Apr 07 15:57:59 2012 +0200 summary: 1) Fix comment. 2) Assert that the source operand is not special. Prevent resulting assert failure (harmless) by initializing flags before calling mpd_qshiftr_inplace. 3) Save a couple of instructions (mpd_zerocoeff already sets digits and len). Reorder initialization to match the order in the mpd_t struct. files: Modules/_decimal/libmpdec/mpdecimal.c | 29 ++++++-------- 1 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -2251,6 +2251,7 @@ { mpd_ssize_t size; + assert(!mpd_isspecial(a)); assert(n >= 0); if (mpd_iszerocoeff(a) || n == 0) { @@ -2265,9 +2266,9 @@ _mpd_baseshiftl(result->data, a->data, size, a->len, n); mpd_copy_flags(result, a); - result->len = size; result->exp = a->exp; result->digits = a->digits+n; + result->len = size; return 1; } @@ -2295,9 +2296,9 @@ } /* - * Same as mpd_qshiftr(), but 'result' is a static array. It is the - * caller's responsibility to make sure that the array is big enough. - * The function cannot fail. + * Same as mpd_qshiftr(), but 'result' is an mpd_t with a static coefficient. + * It is the caller's responsibility to ensure that the coefficient is big + * enough. The function cannot fail. */ mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n) @@ -2305,6 +2306,7 @@ mpd_uint_t rnd; mpd_ssize_t size; + assert(!mpd_isspecial(a)); assert(n >= 0); if (mpd_iszerocoeff(a) || n == 0) { @@ -2315,18 +2317,16 @@ if (n >= a->digits) { rnd = _mpd_get_rnd(a->data, a->len, (n==a->digits)); mpd_zerocoeff(result); - result->digits = 1; - size = 1; } else { result->digits = a->digits-n; size = mpd_digits_to_size(result->digits); rnd = _mpd_baseshiftr(result->data, a->data, a->len, n); + result->len = size; } mpd_copy_flags(result, a); result->exp = a->exp; - result->len = size; return rnd; } @@ -2343,6 +2343,7 @@ mpd_uint_t rnd; mpd_ssize_t size; + assert(!mpd_isspecial(result)); assert(n >= 0); if (mpd_iszerocoeff(result) || n == 0) { @@ -2352,8 +2353,6 @@ if (n >= result->digits) { rnd = _mpd_get_rnd(result->data, result->len, (n==result->digits)); mpd_zerocoeff(result); - result->digits = 1; - size = 1; } else { rnd = _mpd_baseshiftr(result->data, result->data, result->len, n); @@ -2361,9 +2360,8 @@ size = mpd_digits_to_size(result->digits); /* reducing the size cannot fail */ mpd_qresize(result, size, &dummy); - } - - result->len = size; + result->len = size; + } return rnd; } @@ -2381,6 +2379,7 @@ mpd_uint_t rnd; mpd_ssize_t size; + assert(!mpd_isspecial(a)); assert(n >= 0); if (mpd_iszerocoeff(a) || n == 0) { @@ -2393,8 +2392,6 @@ if (n >= a->digits) { rnd = _mpd_get_rnd(a->data, a->len, (n==a->digits)); mpd_zerocoeff(result); - result->digits = 1; - size = 1; } else { result->digits = a->digits-n; @@ -2410,11 +2407,11 @@ } rnd = _mpd_baseshiftr(result->data, a->data, a->len, n); } + result->len = size; } mpd_copy_flags(result, a); result->exp = a->exp; - result->len = size; return rnd; } @@ -3485,6 +3482,7 @@ newsize = _mpd_real_size(q->data, newsize); /* resize to smaller cannot fail */ mpd_qresize(q, newsize, status); + mpd_set_flags(q, sign_a^sign_b); q->len = newsize; mpd_setdigits(q); @@ -3502,7 +3500,6 @@ exp += shift; } - mpd_set_flags(q, sign_a^sign_b); q->exp = exp; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 16:12:26 2012 From: python-checkins at python.org (stefan.krah) Date: Sat, 07 Apr 2012 16:12:26 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?b?KTogTWVyZ2Uu?= Message-ID: http://hg.python.org/cpython/rev/4862619fe28b changeset: 76152:4862619fe28b parent: 76151:a80a579282c7 parent: 76150:51b4bddd0e92 user: Stefan Krah date: Sat Apr 07 16:10:04 2012 +0200 summary: Merge. files: .hgtags | 2 + Doc/library/socket.rst | 25 ++ Lib/importlib/test/import_/test_packages.py | 6 +- Lib/socket.py | 10 +- Lib/test/test_asyncore.py | 7 +- Lib/test/test_site.py | 5 +- Lib/test/test_socket.py | 105 ++++++++++ Lib/test/test_tools.py | 27 ++ Misc/NEWS | 5 + Modules/_io/textio.c | 2 +- Modules/socketmodule.c | 73 ++++++- Tools/scripts/pdeps.py | 10 +- 12 files changed, 258 insertions(+), 19 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -78,6 +78,8 @@ 32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1 c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4 ee26aca3219cf4bb0b93352e83edcc9cb28c7802 v3.1.5rc1 +75db2bc69fc9a3e4801e94e3e19801cb096208d8 v3.1.5rc2 +7395330e495ec3316862ca1f6ce0aaf7bdf6785b v3.1.5 b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1 56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2 da012d9a2c23d144e399d2e01a55b8a83ad94573 v3.2a3 diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -680,6 +680,16 @@ .. versionadded:: 3.3 +.. function:: fromshare(data) + + Instantiate a socket from data obtained from :meth:`~socket.share`. + The socket is assumed to be in blocking mode. + + Availability: Windows. + + .. versionadded:: 3.3 + + .. data:: SocketType This is a Python type object that represents the socket object type. It is the @@ -1082,6 +1092,21 @@ are disallowed. If *how* is :const:`SHUT_RDWR`, further sends and receives are disallowed. + +.. method:: socket.share(process_id) + + :platform: Windows + + Duplacet a socket and prepare it for sharing with a target process. The + target process must be provided with *process_id*. The resulting bytes object + can then be passed to the target process using some form of interprocess + communication and the socket can be recreated there using :func:`fromshare`. + Once this method has been called, it is safe to close the socket since + the operating system has already duplicated it for the target process. + + .. versionadded:: 3.3 + + Note that there are no methods :meth:`read` or :meth:`write`; use :meth:`~socket.recv` and :meth:`~socket.send` without *flags* argument instead. diff --git a/Lib/importlib/test/import_/test_packages.py b/Lib/importlib/test/import_/test_packages.py --- a/Lib/importlib/test/import_/test_packages.py +++ b/Lib/importlib/test/import_/test_packages.py @@ -3,6 +3,7 @@ import sys import unittest import importlib +from test import support class ParentModuleTests(unittest.TestCase): @@ -38,7 +39,10 @@ module_code={'mod': module_injection}) with mock_modules as mock: with util.import_state(meta_path=[mock]): - submodule = import_util.import_(subname) + try: + submodule = import_util.import_(subname) + finally: + support.unload(subname) def test_main(): diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -12,6 +12,7 @@ socket() -- create a new socket object socketpair() -- create a pair of new socket objects [*] fromfd() -- create a socket object from an open file descriptor [*] +fromshare() -- create a socket object from data received from socket.share() [*] gethostname() -- return the current hostname gethostbyname() -- map a hostname to its IP number gethostbyaddr() -- map an IP number or hostname to DNS info @@ -209,7 +210,6 @@ self._closed = True return super().detach() - def fromfd(fd, family, type, proto=0): """ fromfd(fd, family, type[, proto]) -> socket object @@ -219,6 +219,14 @@ nfd = dup(fd) return socket(family, type, proto, nfd) +if hasattr(_socket.socket, "share"): + def fromshare(info): + """ fromshare(info) -> socket object + + Create a socket object from a the bytes object returned by + socket.share(pid). + """ + return socket(0, 0, 0, info) if hasattr(_socket, "socketpair"): diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -74,15 +74,16 @@ pass else: n = 200 - while n > 0: - r, w, e = select.select([conn], [], []) + start = time.time() + while n > 0 and time.time() - start < 3.0: + r, w, e = select.select([conn], [], [], 0.1) if r: + n -= 1 data = conn.recv(10) # keep everything except for the newline terminator buf.write(data.replace(b'\n', b'')) if b'\n' in data: break - n -= 1 time.sleep(0.01) conn.close() diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -39,6 +39,7 @@ self.old_base = site.USER_BASE self.old_site = site.USER_SITE self.old_prefixes = site.PREFIXES + self.original_vars = sysconfig._CONFIG_VARS self.old_vars = copy(sysconfig._CONFIG_VARS) def tearDown(self): @@ -47,7 +48,9 @@ site.USER_BASE = self.old_base site.USER_SITE = self.old_site site.PREFIXES = self.old_prefixes - sysconfig._CONFIG_VARS = self.old_vars + sysconfig._CONFIG_VARS = self.original_vars + sysconfig._CONFIG_VARS.clear() + sysconfig._CONFIG_VARS.update(self.old_vars) def test_makepath(self): # Test makepath() have an absolute path for its first return value 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 @@ -26,6 +26,10 @@ import fcntl except ImportError: fcntl = False +try: + import multiprocessing +except ImportError: + multiprocessing = False HOST = support.HOST MSG = 'Michael Gilfix was here\u1234\r\n'.encode('utf-8') ## test unicode string and carriage return @@ -4643,6 +4647,106 @@ socket.setdefaulttimeout(t) + at unittest.skipUnless(os.name == "nt", "Windows specific") + at unittest.skipUnless(multiprocessing, "need multiprocessing") +class TestSocketSharing(SocketTCPTest): + # This must be classmethod and not staticmethod or multiprocessing + # won't be able to bootstrap it. + @classmethod + def remoteProcessServer(cls, q): + # Recreate socket from shared data + sdata = q.get() + message = q.get() + + s = socket.fromshare(sdata) + s2, c = s.accept() + + # Send the message + s2.sendall(message) + s2.close() + s.close() + + def testShare(self): + # Transfer the listening server socket to another process + # and service it from there. + + # Create process: + q = multiprocessing.Queue() + p = multiprocessing.Process(target=self.remoteProcessServer, args=(q,)) + p.start() + + # Get the shared socket data + data = self.serv.share(p.pid) + + # Pass the shared socket to the other process + addr = self.serv.getsockname() + self.serv.close() + q.put(data) + + # The data that the server will send us + message = b"slapmahfro" + q.put(message) + + # Connect + s = socket.create_connection(addr) + # listen for the data + m = [] + while True: + data = s.recv(100) + if not data: + break + m.append(data) + s.close() + received = b"".join(m) + self.assertEqual(received, message) + p.join() + + def testShareLength(self): + data = self.serv.share(os.getpid()) + self.assertRaises(ValueError, socket.fromshare, data[:-1]) + self.assertRaises(ValueError, socket.fromshare, data+b"foo") + + def compareSockets(self, org, other): + # socket sharing is expected to work only for blocking socket + # since the internal python timout value isn't transfered. + self.assertEqual(org.gettimeout(), None) + self.assertEqual(org.gettimeout(), other.gettimeout()) + + self.assertEqual(org.family, other.family) + self.assertEqual(org.type, other.type) + # If the user specified "0" for proto, then + # internally windows will have picked the correct value. + # Python introspection on the socket however will still return + # 0. For the shared socket, the python value is recreated + # from the actual value, so it may not compare correctly. + if org.proto != 0: + self.assertEqual(org.proto, other.proto) + + def testShareLocal(self): + data = self.serv.share(os.getpid()) + s = socket.fromshare(data) + try: + self.compareSockets(self.serv, s) + finally: + s.close() + + def testTypes(self): + families = [socket.AF_INET, socket.AF_INET6] + types = [socket.SOCK_STREAM, socket.SOCK_DGRAM] + for f in families: + for t in types: + source = socket.socket(f, t) + try: + data = source.share(os.getpid()) + shared = socket.fromshare(data) + try: + self.compareSockets(source, shared) + finally: + shared.close() + finally: + source.close() + + def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, TestExceptions, BufferIOTest, BasicTCPTest2, BasicUDPTest, UDPTimeoutTest ] @@ -4699,6 +4803,7 @@ # These are slow when setitimer() is not available InterruptedRecvTimeoutTest, InterruptedSendTimeoutTest, + TestSocketSharing, ]) thread_info = support.threading_setup() diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -6,8 +6,10 @@ import os import sys +import imp import unittest import sysconfig +import tempfile from test import support from test.script_helper import assert_python_ok @@ -72,6 +74,31 @@ import analyze_dxp +class PdepsTests(unittest.TestCase): + + @classmethod + def setUpClass(self): + path = os.path.join(scriptsdir, 'pdeps.py') + self.pdeps = imp.load_source('pdeps', path) + + @classmethod + def tearDownClass(self): + if 'pdeps' in sys.modules: + del sys.modules['pdeps'] + + def test_process_errors(self): + # Issue #14492: m_import.match(line) can be None. + with tempfile.TemporaryDirectory() as tmpdir: + fn = os.path.join(tmpdir, 'foo') + with open(fn, 'w') as stream: + stream.write("#!/this/will/fail") + self.pdeps.process(fn, {}) + + def test_inverse_attribute_error(self): + # Issue #14492: this used to fail with an AttributeError. + self.pdeps.inverse({'a': []}) + + def test_main(): support.run_unittest(*[obj for obj in globals().values() if isinstance(obj, type)]) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,8 @@ Library ------- +- Don't Py_DECREF NULL variable in io.IncrementalNewlineDecoder. + - Issue #8515: Set __file__ when run file in IDLE. Initial patch by Bruce Frederiksen. @@ -230,6 +232,9 @@ - Issue #14210: pdb now has tab-completion not only for command names, but also for their arguments, wherever possible. +- Issue #14310: Sockets can now be with other processes on Windows using + the api socket.socket.share() and socket.fromshare(). + Build ----- diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -460,7 +460,7 @@ output = PyUnicode_FromKindAndData(kind, translated, out); PyMem_Free(translated); if (!output) - goto error; + return NULL; } self->seennl |= seennl; } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3771,6 +3771,34 @@ Control the socket with WSAIoctl syscall. Currently supported 'cmd' values are\n\ SIO_RCVALL: 'option' must be one of the socket.RCVALL_* constants.\n\ SIO_KEEPALIVE_VALS: 'option' is a tuple of (onoff, timeout, interval)."); +#endif + +#if defined(MS_WINDOWS) +static PyObject* +sock_share(PySocketSockObject *s, PyObject *arg) +{ + WSAPROTOCOL_INFO info; + DWORD processId; + int result; + + if (!PyArg_ParseTuple(arg, "I", &processId)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = WSADuplicateSocket(s->sock_fd, processId, &info); + Py_END_ALLOW_THREADS + if (result == SOCKET_ERROR) + return set_error(); + return PyBytes_FromStringAndSize((const char*)&info, sizeof(info)); +} +PyDoc_STRVAR(sock_share_doc, +"share(process_id) -> bytes\n\ +\n\ +Share the socket with another process. The target process id\n\ +must be provided and the resulting bytes object passed to the target\n\ +process. There the shared socket can be instantiated by calling\n\ +socket.fromshare()."); + #endif @@ -3803,6 +3831,10 @@ {"ioctl", (PyCFunction)sock_ioctl, METH_VARARGS, sock_ioctl_doc}, #endif +#if defined(MS_WINDOWS) + {"share", (PyCFunction)sock_share, METH_VARARGS, + sock_share_doc}, +#endif {"listen", (PyCFunction)sock_listen, METH_O, listen_doc}, {"recv", (PyCFunction)sock_recv, METH_VARARGS, @@ -3930,13 +3962,40 @@ return -1; if (fdobj != NULL && fdobj != Py_None) { - fd = PyLong_AsSocket_t(fdobj); - if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) - return -1; - if (fd == INVALID_SOCKET) { - PyErr_SetString(PyExc_ValueError, - "can't use invalid socket value"); - return -1; +#ifdef MS_WINDOWS + /* recreate a socket that was duplicated */ + if (PyBytes_Check(fdobj)) { + WSAPROTOCOL_INFO info; + if (PyBytes_GET_SIZE(fdobj) != sizeof(info)) { + PyErr_Format(PyExc_ValueError, + "socket descriptor string has wrong size, " + "should be %zu bytes.", sizeof(info)); + return -1; + } + memcpy(&info, PyBytes_AS_STRING(fdobj), sizeof(info)); + Py_BEGIN_ALLOW_THREADS + fd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, &info, 0, WSA_FLAG_OVERLAPPED); + Py_END_ALLOW_THREADS + if (fd == INVALID_SOCKET) { + set_error(); + return -1; + } + family = info.iAddressFamily; + type = info.iSocketType; + proto = info.iProtocol; + } + else +#endif + { + fd = PyLong_AsSocket_t(fdobj); + if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) + return -1; + if (fd == INVALID_SOCKET) { + PyErr_SetString(PyExc_ValueError, + "can't use invalid socket value"); + return -1; + } } } else { diff --git a/Tools/scripts/pdeps.py b/Tools/scripts/pdeps.py --- a/Tools/scripts/pdeps.py +++ b/Tools/scripts/pdeps.py @@ -76,10 +76,9 @@ nextline = fp.readline() if not nextline: break line = line[:-1] + nextline - if m_import.match(line) >= 0: - (a, b), (a1, b1) = m_import.regs[:2] - elif m_from.match(line) >= 0: - (a, b), (a1, b1) = m_from.regs[:2] + m_found = m_import.match(line) or m_from.match(line) + if m_found: + (a, b), (a1, b1) = m_found.regs[:2] else: continue words = line[a1:b1].split(',') # print '#', line, words @@ -87,6 +86,7 @@ word = word.strip() if word not in list: list.append(word) + fp.close() # Compute closure (this is in fact totally general) @@ -123,7 +123,7 @@ def inverse(table): inv = {} for key in table.keys(): - if not inv.has_key(key): + if key not in inv: inv[key] = [] for item in table[key]: store(inv, item, key) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 19:23:04 2012 From: python-checkins at python.org (georg.brandl) Date: Sat, 07 Apr 2012 19:23:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Closes_=2314511?= =?utf8?q?=3A_fix_wrong_opensearch_link_for_3=2E2_docs=2E?= Message-ID: http://hg.python.org/cpython/rev/7f123dec2731 changeset: 76153:7f123dec2731 branch: 3.2 parent: 76147:5b68fd4246fc user: Georg Brandl date: Sat Apr 07 19:22:17 2012 +0200 summary: Closes #14511: fix wrong opensearch link for 3.2 docs. files: Doc/conf.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -91,7 +91,7 @@ } # Output an OpenSearch description file. -html_use_opensearch = 'http://docs.python.org/dev/py3k' +html_use_opensearch = 'http://docs.python.org/3.2' # Additional static files. html_static_path = ['tools/sphinxext/static'] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 19:23:05 2012 From: python-checkins at python.org (georg.brandl) Date: Sat, 07 Apr 2012 19:23:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Closes_=2314511=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/57a8a8f5e0bc changeset: 76154:57a8a8f5e0bc parent: 76152:4862619fe28b parent: 76153:7f123dec2731 user: Georg Brandl date: Sat Apr 07 19:23:00 2012 +0200 summary: Closes #14511: merge with 3.2 files: Doc/conf.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -91,7 +91,7 @@ } # Output an OpenSearch description file. -html_use_opensearch = 'http://docs.python.org/dev/py3k' +html_use_opensearch = 'http://docs.python.org/3.3' # Additional static files. html_static_path = ['tools/sphinxext/static'] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 19:24:43 2012 From: python-checkins at python.org (georg.brandl) Date: Sat, 07 Apr 2012 19:24:43 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Determine_opensearch_URL_fr?= =?utf8?q?om_current_version=2E?= Message-ID: http://hg.python.org/cpython/rev/16ef7e115cf8 changeset: 76155:16ef7e115cf8 user: Georg Brandl date: Sat Apr 07 19:24:40 2012 +0200 summary: Determine opensearch URL from current version. files: Doc/conf.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -91,7 +91,7 @@ } # Output an OpenSearch description file. -html_use_opensearch = 'http://docs.python.org/3.3' +html_use_opensearch = 'http://docs.python.org/' + version # Additional static files. html_static_path = ['tools/sphinxext/static'] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 20:59:39 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 07 Apr 2012 20:59:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_struct_timeval=2Etv=5Fusec_?= =?utf8?q?is_4_bytes_on_64-bit_OS_X_as_it_should_be=2C_but?= Message-ID: http://hg.python.org/cpython/rev/3028c8d46c00 changeset: 76156:3028c8d46c00 user: Brett Cannon date: Sat Apr 07 14:59:29 2012 -0400 summary: struct timeval.tv_usec is 4 bytes on 64-bit OS X as it should be, but is defined as an int while everyone else expects a long regardless of length. files: Modules/selectmodule.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -237,8 +237,12 @@ #endif tv.tv_sec = (long)sec; #else - if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv.tv_usec) == -1) + /* 64-bit OS X has struct timeval.tv_usec as an int (and thus still 4 + bytes as required), but no longer defined by a long. */ + long tv_usec = tv.tv_usec; + if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv_usec) == -1) return NULL; + tv.tv_usec = tv_usec; #endif if (tv.tv_sec < 0) { PyErr_SetString(PyExc_ValueError, "timeout must be non-negative"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 22:39:52 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Sat, 07 Apr 2012 22:39:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314310=3A_Catch_tes?= =?utf8?q?ting_errors_when_trying_to_create_unsupported_socket?= Message-ID: http://hg.python.org/cpython/rev/9b858096044e changeset: 76157:9b858096044e user: Kristj?n Valur J?nsson date: Sat Apr 07 20:38:44 2012 +0000 summary: Issue #14310: Catch testing errors when trying to create unsupported socket types on some platforms. files: Lib/test/test_socket.py | 5 ++++- 1 files changed, 4 insertions(+), 1 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 @@ -4735,7 +4735,10 @@ types = [socket.SOCK_STREAM, socket.SOCK_DGRAM] for f in families: for t in types: - source = socket.socket(f, t) + try: + source = socket.socket(f, t) + except OSError: + continue # This combination is not supported try: data = source.share(os.getpid()) shared = socket.fromshare(data) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 22:44:37 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 07 Apr 2012 22:44:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314522=3A_Avoid_dup?= =?utf8?q?licating_socket_handles_in_multiprocessing=2Econnection=2E?= Message-ID: http://hg.python.org/cpython/rev/f8a92fd084c2 changeset: 76158:f8a92fd084c2 user: Antoine Pitrou date: Sat Apr 07 22:38:52 2012 +0200 summary: Issue #14522: Avoid duplicating socket handles in multiprocessing.connection. Patch by sbt. files: Lib/multiprocessing/connection.py | 15 +++------------ Misc/NEWS | 3 +++ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -591,10 +591,7 @@ def accept(self): s, self._last_accepted = self._socket.accept() - fd = duplicate(s.fileno()) - conn = Connection(fd) - s.close() - return conn + return Connection(s.detach()) def close(self): self._socket.close() @@ -609,9 +606,7 @@ family = address_type(address) with socket.socket( getattr(socket, family) ) as s: s.connect(address) - fd = duplicate(s.fileno()) - conn = Connection(fd) - return conn + return Connection(s.detach()) # # Definitions for connections based on named pipes @@ -665,7 +660,7 @@ def _finalize_pipe_listener(queue, address): sub_debug('closing listener with address=%r', address) for handle in queue: - close(handle) + win32.CloseHandle(handle) def PipeClient(address): ''' @@ -885,7 +880,3 @@ raise if timeout is not None: timeout = deadline - time.time() - - -# Late import because of circular import -from multiprocessing.forking import duplicate, close diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #14522: Avoid duplicating socket handles in multiprocessing.connection. + Patch by sbt. + - Don't Py_DECREF NULL variable in io.IncrementalNewlineDecoder. - Issue #8515: Set __file__ when run file in IDLE. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 7 23:06:40 2012 From: python-checkins at python.org (andrew.svetlov) Date: Sat, 07 Apr 2012 23:06:40 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Publish_pep-419?= Message-ID: http://hg.python.org/peps/rev/fabdbf0c63d6 changeset: 4203:fabdbf0c63d6 user: Andrew Svetlov date: Sun Apr 08 00:06:30 2012 +0300 summary: Publish pep-419 files: pep-0419.txt | 459 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 459 insertions(+), 0 deletions(-) diff --git a/pep-0419.txt b/pep-0419.txt new file mode 100644 --- /dev/null +++ b/pep-0419.txt @@ -0,0 +1,459 @@ +PEP: 419 +Title: Protecting cleanup statements from interruptions +Version: $Revision$ +Last-Modified: $Date$ +Author: Paul Colomiets +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 06-Apr-2012 +Python-Version: 3.3 + + +Abstract +======== + +This PEP proposes a way to protect python code from being interrupted inside +finally statement or context manager. + + +Rationale +========= + +Python has two nice ways to do cleanup. One is a ``finally`` statement +and the other is context manager (or ``with`` statement). Although, +neither of them is protected from ``KeyboardInterrupt`` or +``generator.throw()``. For example:: + + lock.acquire() + try: + print('starting') + do_someting() + finally: + print('finished') + lock.release() + +If ``KeyboardInterrupt`` occurs just after ``print`` function is +executed, lock will not be released. Similarly the following code +using ``with`` statement is affected:: + + from threading import Lock + + class MyLock: + + def __init__(self): + self._lock_impl = lock + + def __enter__(self): + self._lock_impl.acquire() + print("LOCKED") + + def __exit__(self): + print("UNLOCKING") + self._lock_impl.release() + + lock = MyLock() + with lock: + do_something + +If ``KeyboardInterrupt`` occurs near any of the ``print`` statements, +lock will never be released. + + +Coroutine Use Case +------------------ + +Similar case occurs with coroutines. Usually coroutine libraries want +to interrupt coroutine with a timeout. There is a +``generator.throw()`` method for this use case, but there are no +method to know is it currently yielded from inside a ``finally``. + +Example that uses yield-based coroutines follows. Code looks +similar using any of the popular coroutine libraries Monocle [1]_, +Bluelet [2]_, or Twisted [3]_. :: + + def run_locked() + yield connection.sendall('LOCK') + try: + yield do_something() + yield do_something_else() + finally: + yield connection.sendall('UNLOCK') + + with timeout(5): + yield run_locked() + +In the example above ``yield something`` means pause executing current +coroutine and execute coroutine ``something`` until it finished +execution. So that library keeps stack of generators itself. The +``connection.sendall`` waits until socket is writable and does thing +similar to what ``socket.sendall`` does. + +The ``with`` statement ensures that all that code is executed within 5 +seconds timeout. It does so by registering a callback in main loop, +which calls ``generator.throw()`` to the top-most frame in the +coroutine stack when timeout happens. + +The ``greenlets`` extension works in similar way, except it doesn't +need ``yield`` to enter new stack frame. Otherwise considerations are +similar. + + +Specification +============= + +Frame Flag 'f_in_cleanup' +------------------------- + +A new flag on frame object is proposed. It is set to ``True`` if this +frame is currently in the ``finally`` suite. Internally it must be +implemented as a counter of nested finally statements currently +executed. + +The internal counter is also incremented when entering ``WITH_SETUP`` +bytecode and ``WITH_CLEANUP`` bytecode, and is decremented when +leaving that bytecode. This allows to protect ``__enter__`` and +``__exit__`` methods too. + + +Function 'sys.setcleanuphook' +----------------------------- + +A new function for the ``sys`` module is proposed. This function sets +a callback which is executed every time ``f_in_cleanup`` becomes +``False``. Callbacks gets ``frame`` as it's sole argument so it can +get some evindence where it is called from. + +The setting is thread local and is stored inside ``PyThreadState`` +structure. + + +Inspect Module Enhancements +--------------------------- + +Two new functions are proposed for ``inspect`` module: +``isframeincleanup`` and ``getcleanupframe``. + +``isframeincleanup`` given ``frame`` object or ``generator`` object as +sole argument returns the value of ``f_in_cleanup`` attribute of a +frame itself or of the ``gi_frame`` attribute of a generator. + +``getcleanupframe`` given ``frame`` object as sole argument returns +the innermost frame which has true value of ``f_in_cleanup`` or +``None`` if no frames in the stack has the attribute set. It starts to +inspect from specified frame and walks to outer frames using +``f_back`` pointers, just like ``getouterframes`` does. + + +Example +======= + +Example implementation of ``SIGINT`` handler that interrupts safely +might look like:: + + import inspect, sys, functools + + def sigint_handler(sig, frame) + if inspect.getcleanupframe(frame) is None: + raise KeyboardInterrupt() + sys.setcleanuphook(functools.partial(sigint_handler, 0)) + +Coroutine example is out of scope of this document, because it's +implemention depends very much on a trampoline (or main loop) used by +coroutine library. + + +Unresolved Issues +================= + +Interruption Inside With Statement Expression +--------------------------------------------- + +Given the statement:: + + with open(filename): + do_something() + +Python can be interrupted after ``open`` is called, but before +``SETUP_WITH`` bytecode is executed. There are two possible decisions: + +* Protect expression inside ``with`` statement. This would need + another bytecode, since currently there is no delimiter at the start + of ``with`` expression + +* Let user write a wrapper if he considers it's important for his + use-case. Safe wrapper code might look like the following:: + + class FileWrapper(object): + + def __init__(self, filename, mode): + self.filename = filename + self.mode = mode + + def __enter__(self): + self.file = open(self.filename, self.mode) + + def __exit__(self): + self.file.close() + + Alternatively it can be written using context manager:: + + @contextmanager + def open_wrapper(filename, mode): + file = open(filename, mode) + try: + yield file + finally: + file.close() + + This code is safe, as first part of generator (before yield) is + executed inside ``WITH_SETUP`` bytecode of caller + + +Exception Propagation +--------------------- + +Sometimes ``finally`` block or ``__enter__/__exit__`` method can be +exited with an exception. Usually it's not a problem, since more +important exception like ``KeyboardInterrupt`` or ``SystemExit`` +should be thrown instead. But it may be nice to be able to keep +original exception inside a ``__context__`` attibute. So cleanup hook +signature may grow an exception argument:: + + def sigint_handler(sig, frame) + if inspect.getcleanupframe(frame) is None: + raise KeyboardInterrupt() + sys.setcleanuphook(retry_sigint) + + def retry_sigint(frame, exception=None): + if inspect.getcleanupframe(frame) is None: + raise KeyboardInterrupt() from exception + +.. note:: + + No need to have three arguments like in ``__exit__`` method since + we have a ``__traceback__`` attribute in exception in Python 3.x + +Although, this will set ``__cause__`` for the exception, which is not +exactly what's intended. So some hidden interpeter logic may be used +to put ``__context__`` attribute on every exception raised in cleanup +hook. + + +Interruption Between Acquiring Resource and Try Block +----------------------------------------------------- + +Example from the first section is not totally safe. Let's look closer:: + + lock.acquire() + try: + do_something() + finally: + lock.release() + +There is no way it can be fixed without modifying the code. The actual +fix of this code depends very much on use case. + +Usually code can be fixed using a ``with`` statement:: + + with lock: + do_something() + +Although, for coroutines you usually can't use ``with`` statement +because you need to ``yield`` for both aquire and release operations. +So code might be rewritten as following:: + + try: + yield lock.acquire() + do_something() + finally: + yield lock.release() + +The actual lock code might need more code to support this use case, +but implementation is usually trivial, like check if lock has been +acquired and unlock if it is. + + +Setting Interruption Context Inside Finally Itself +-------------------------------------------------- + +Some coroutine libraries may need to set a timeout for the finally +clause itself. For example:: + + try: + do_something() + finally: + with timeout(0.5): + try: + yield do_slow_cleanup() + finally: + yield do_fast_cleanup() + +With current semantics timeout will either protect +the whole ``with`` block or nothing at all, depending on the +implementation of a library. What the author is intended is to treat +``do_slow_cleanup`` as an ordinary code, and ``do_fast_cleanup`` as a +cleanup (non-interruptible one). + +Similar case might occur when using greenlets or tasklets. + +This case can be fixed by exposing ``f_in_cleanup`` as a counter, and +by calling cleanup hook on each decrement. Corouting library may then +remember the value at timeout start, and compare it on each hook +execution. + +But in practice example is considered to be too obscure to take in +account. + + +Alternative Python Implementations Support +========================================== + +We consider ``f_in_cleanup`` and implementation detail. The actual +implementation may have some fake frame-like object passed to signal +handler, cleanup hook and returned from ``getcleanupframe``. The only +requirement is that ``inspect`` module functions work as expected on +that objects. For this reason we also allow to pass a ``generator`` +object to a ``isframeincleanup`` function, this disables need to use +``gi_frame`` attribute. + +It may need to be specified that ``getcleanupframe`` must return the +same object that will be passed to cleanup hook at next invocation. + + +Alternative Names +================= + +Original proposal had ``f_in_finally`` flag. The original intention +was to protect ``finally`` clauses. But as it grew up to protecting +``__enter__`` and ``__exit__`` methods too, the ``f_in_cleanup`` +method seems better. Although ``__enter__`` method is not a cleanup +routine, it at least relates to cleanup done by context managers. + +``setcleanuphook``, ``isframeincleanup`` and ``getcleanupframe`` can +be unobscured to ``set_cleanup_hook``, ``is_frame_in_cleanup`` and +``get_cleanup_frame``, althought they follow convention of their +respective modules. + + +Alternative Proposals +===================== + +Propagating 'f_in_cleanup' Flag Automatically +----------------------------------------------- + +This can make ``getcleanupframe`` unnecessary. But for yield based +coroutines you need to propagate it yourself. Making it writable leads +to somewhat unpredictable behavior of ``setcleanuphook`` + + +Add Bytecodes 'INCR_CLEANUP', 'DECR_CLEANUP' +-------------------------------------------- + +These bytecodes can be used to protect expression inside ``with`` +statement, as well as making counter increments more explicit and easy +to debug (visible inside a disassembly). Some middle ground might be +chosen, like ``END_FINALLY`` and ``SETUP_WITH`` imlicitly decrements +counter (``END_FINALLY`` is present at end of ``with`` suite). + +Although, adding new bytecodes must be considered very carefully. + + +Expose 'f_in_cleanup' as a Counter +---------------------------------- + +The original intention was to expose minimum needed functionality. +Although, as we consider frame flag ``f_in_cleanup`` as an +implementation detail, we may expose it as a counter. + +Similarly, if we have a counter we may need to have cleanup hook +called on every counter decrement. It's unlikely have much performance +impact as nested finally clauses are unlikely common case. + + +Add code object flag 'CO_CLEANUP' +--------------------------------- + +As an alternative to set flag inside ``WITH_SETUP``, and +``WITH_CLEANUP`` bytecodes we can introduce a flag ``CO_CLEANUP``. +When interpreter starts to execute code with ``CO_CLEANUP`` set, it +sets ``f_in_cleanup`` for the whole function body. This flag is set +for code object of ``__enter__`` and ``__exit__`` special methods. +Technically it might be set on functions called ``__enter__`` and +``__exit__``. + +This seems to be less clear solution. It also covers the case where +``__enter__`` and ``__exit__`` are called manually. This may be +accepted either as feature or as a unnecessary side-effect (unlikely +as a bug). + +It may also impose a problem when ``__enter__`` or ``__exit__`` +function are implemented in C, as there usually no frame to check for +``f_in_cleanup`` flag. + + +Have Cleanup Callback on Frame Object Itself +---------------------------------------------- + +Frame may be extended to have ``f_cleanup_callback`` which is called +when ``f_in_cleanup`` is reset to 0. It would help to register +different callbacks to different coroutines. + +Despite apparent beauty. This solution doesn't add anything. As there +are two primary use cases: + +* Set callback in signal handler. The callback is inherently single + one for this case + +* Use single callback per loop for coroutine use case. And in almost + all cases there is only one loop per thread + + +No Cleanup Hook +--------------- + +Original proposal included no cleanup hook specification. As there are +few ways to achieve the same using current tools: + +* Use ``sys.settrace`` and ``f_trace`` callback. It may impose some + problem to debugging, and has big performance impact (although, + interrupting doesn't happen very often) + +* Sleep a bit more and try again. For coroutine library it's easy. For + signals it may be achieved using ``alert``. + +Both methods are considered too impractical and a way to catch exit +from ``finally`` statement is proposed. + + +References +========== + +.. [1] Monocle + https://github.com/saucelabs/monocle + +.. [2] Bluelet + https://github.com/sampsyo/bluelet + +.. [3] Twisted: inlineCallbacks + http://twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.html + +.. [4] Original discussion + http://mail.python.org/pipermail/python-ideas/2012-April/014705.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: http://hg.python.org/peps From python-checkins at python.org Sun Apr 8 00:44:01 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 08 Apr 2012 00:44:01 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Edit_PEP_419=3A_fix_grammar=2C?= =?utf8?q?_spelling_and_formatting=2E?= Message-ID: http://hg.python.org/peps/rev/a2628399ebba changeset: 4204:a2628399ebba user: Georg Brandl date: Sun Apr 08 00:44:05 2012 +0200 summary: Edit PEP 419: fix grammar, spelling and formatting. files: pep-0419.txt | 493 ++++++++++++++++++++------------------ 1 files changed, 253 insertions(+), 240 deletions(-) diff --git a/pep-0419.txt b/pep-0419.txt --- a/pep-0419.txt +++ b/pep-0419.txt @@ -13,90 +13,93 @@ Abstract ======== -This PEP proposes a way to protect python code from being interrupted inside -finally statement or context manager. +This PEP proposes a way to protect Python code from being interrupted +inside a finally clause or during context manager cleanup. Rationale ========= -Python has two nice ways to do cleanup. One is a ``finally`` statement -and the other is context manager (or ``with`` statement). Although, -neither of them is protected from ``KeyboardInterrupt`` or -``generator.throw()``. For example:: +Python has two nice ways to do cleanup. One is a ``finally`` +statement and the other is a context manager (usually called using a +``with`` statement). However, neither is protected from interruption +by ``KeyboardInterrupt`` or ``GeneratorExit`` caused by +``generator.throw()``. For example:: - lock.acquire() - try: - print('starting') - do_someting() - finally: - print('finished') - lock.release() + lock.acquire() + try: + print('starting') + do_something() + finally: + print('finished') + lock.release() -If ``KeyboardInterrupt`` occurs just after ``print`` function is -executed, lock will not be released. Similarly the following code -using ``with`` statement is affected:: +If ``KeyboardInterrupt`` occurs just after the second ``print()`` +call, the lock will not be released. Similarly, the following code +using the ``with`` statement is affected:: - from threading import Lock + from threading import Lock - class MyLock: + class MyLock: - def __init__(self): - self._lock_impl = lock + def __init__(self): + self._lock_impl = Lock() - def __enter__(self): - self._lock_impl.acquire() - print("LOCKED") + def __enter__(self): + self._lock_impl.acquire() + print("LOCKED") - def __exit__(self): - print("UNLOCKING") - self._lock_impl.release() + def __exit__(self): + print("UNLOCKING") + self._lock_impl.release() - lock = MyLock() - with lock: - do_something + lock = MyLock() + with lock: + do_something -If ``KeyboardInterrupt`` occurs near any of the ``print`` statements, +If ``KeyboardInterrupt`` occurs near any of the ``print()`` calls, the lock will never be released. Coroutine Use Case ------------------ -Similar case occurs with coroutines. Usually coroutine libraries want -to interrupt coroutine with a timeout. There is a -``generator.throw()`` method for this use case, but there are no -method to know is it currently yielded from inside a ``finally``. +A similar case occurs with coroutines. Usually coroutine libraries +want to interrupt the coroutine with a timeout. The +``generator.throw()`` method works for this use case, but there is no +way of knowing if the coroutine is currently suspended from inside a +``finally`` clause. -Example that uses yield-based coroutines follows. Code looks +An example that uses yield-based coroutines follows. The code looks similar using any of the popular coroutine libraries Monocle [1]_, Bluelet [2]_, or Twisted [3]_. :: - def run_locked() - yield connection.sendall('LOCK') - try: - yield do_something() - yield do_something_else() - finally: - yield connection.sendall('UNLOCK') + def run_locked(): + yield connection.sendall('LOCK') + try: + yield do_something() + yield do_something_else() + finally: + yield connection.sendall('UNLOCK') - with timeout(5): - yield run_locked() + with timeout(5): + yield run_locked() -In the example above ``yield something`` means pause executing current -coroutine and execute coroutine ``something`` until it finished -execution. So that library keeps stack of generators itself. The -``connection.sendall`` waits until socket is writable and does thing -similar to what ``socket.sendall`` does. +In the example above, ``yield something`` means to pause executing the +current coroutine and to execute coroutine ``something`` until it +finishes execution. Therefore the coroutine library itself needs to +maintain a stack of generators. The ``connection.sendall()`` call waits +until the socket is writable and does a similar thing to what +``socket.sendall()`` does. -The ``with`` statement ensures that all that code is executed within 5 -seconds timeout. It does so by registering a callback in main loop, -which calls ``generator.throw()`` to the top-most frame in the -coroutine stack when timeout happens. +The ``with`` statement ensures that all code is executed within 5 +seconds timeout. It does so by registering a callback in the main +loop, which calls ``generator.throw()`` on the top-most frame in the +coroutine stack when a timeout happens. -The ``greenlets`` extension works in similar way, except it doesn't -need ``yield`` to enter new stack frame. Otherwise considerations are -similar. +The ``greenlets`` extension works in a similar way, except that it +doesn't need ``yield`` to enter a new stack frame. Otherwise +considerations are similar. Specification @@ -105,62 +108,63 @@ Frame Flag 'f_in_cleanup' ------------------------- -A new flag on frame object is proposed. It is set to ``True`` if this -frame is currently in the ``finally`` suite. Internally it must be -implemented as a counter of nested finally statements currently -executed. +A new flag on the frame object is proposed. It is set to ``True`` if +this frame is currently executing a ``finally`` clause. Internally, +the flag must be implemented as a counter of nested finally statements +currently being executed. -The internal counter is also incremented when entering ``WITH_SETUP`` -bytecode and ``WITH_CLEANUP`` bytecode, and is decremented when -leaving that bytecode. This allows to protect ``__enter__`` and -``__exit__`` methods too. +The internal counter also needs to be incremented during execution of +the ``SETUP_WITH`` and ``WITH_CLEANUP`` bytecodes, and decremented +when execution for these bytecodes is finished. This allows to also +protect ``__enter__()`` and ``__exit__()`` methods. Function 'sys.setcleanuphook' ----------------------------- -A new function for the ``sys`` module is proposed. This function sets +A new function for the ``sys`` module is proposed. This function sets a callback which is executed every time ``f_in_cleanup`` becomes -``False``. Callbacks gets ``frame`` as it's sole argument so it can -get some evindence where it is called from. +false. Callbacks get a frame object as their sole argument, so that +they can figure out where they are called from. -The setting is thread local and is stored inside ``PyThreadState`` -structure. +The setting is thread local and must be stored in the +``PyThreadState`` structure. Inspect Module Enhancements --------------------------- -Two new functions are proposed for ``inspect`` module: -``isframeincleanup`` and ``getcleanupframe``. +Two new functions are proposed for the ``inspect`` module: +``isframeincleanup()`` and ``getcleanupframe()``. -``isframeincleanup`` given ``frame`` object or ``generator`` object as -sole argument returns the value of ``f_in_cleanup`` attribute of a +``isframeincleanup()``, given a frame or generator object as its sole +argument, returns the value of the ``f_in_cleanup`` attribute of a frame itself or of the ``gi_frame`` attribute of a generator. -``getcleanupframe`` given ``frame`` object as sole argument returns -the innermost frame which has true value of ``f_in_cleanup`` or -``None`` if no frames in the stack has the attribute set. It starts to -inspect from specified frame and walks to outer frames using -``f_back`` pointers, just like ``getouterframes`` does. +``getcleanupframe()``, given a frame object as its sole argument, +returns the innermost frame which has a true value of +``f_in_cleanup``, or ``None`` if no frames in the stack have a nonzero +value for that attribute. It starts to inspect from the specified +frame and walks to outer frames using ``f_back`` pointers, just like +``getouterframes()`` does. Example ======= -Example implementation of ``SIGINT`` handler that interrupts safely +An example implementation of a SIGINT handler that interrupts safely might look like:: - import inspect, sys, functools + import inspect, sys, functools - def sigint_handler(sig, frame) - if inspect.getcleanupframe(frame) is None: - raise KeyboardInterrupt() - sys.setcleanuphook(functools.partial(sigint_handler, 0)) + def sigint_handler(sig, frame): + if inspect.getcleanupframe(frame) is None: + raise KeyboardInterrupt() + sys.setcleanuphook(functools.partial(sigint_handler, 0)) -Coroutine example is out of scope of this document, because it's -implemention depends very much on a trampoline (or main loop) used by -coroutine library. +A coroutine example is out of scope of this document, because its +implementation depends very much on a trampoline (or main loop) used +by coroutine library. Unresolved Issues @@ -169,277 +173,284 @@ Interruption Inside With Statement Expression --------------------------------------------- -Given the statement:: +Given the statement :: - with open(filename): - do_something() + with open(filename): + do_something() -Python can be interrupted after ``open`` is called, but before -``SETUP_WITH`` bytecode is executed. There are two possible decisions: +Python can be interrupted after ``open()`` is called, but before the +``SETUP_WITH`` bytecode is executed. There are two possible +decisions: -* Protect expression inside ``with`` statement. This would need - another bytecode, since currently there is no delimiter at the start - of ``with`` expression +* Protect ``with`` expressions. This would require another bytecode, + since currently there is no way of recognizing the start of the + ``with`` expression. -* Let user write a wrapper if he considers it's important for his - use-case. Safe wrapper code might look like the following:: +* Let the user write a wrapper if he considers it important for the + use-case. A safe wrapper might look like this:: - class FileWrapper(object): + class FileWrapper(object): - def __init__(self, filename, mode): - self.filename = filename - self.mode = mode + def __init__(self, filename, mode): + self.filename = filename + self.mode = mode - def __enter__(self): - self.file = open(self.filename, self.mode) + def __enter__(self): + self.file = open(self.filename, self.mode) - def __exit__(self): - self.file.close() + def __exit__(self): + self.file.close() - Alternatively it can be written using context manager:: + Alternatively it can be written using the ``contextmanager()`` + decorator:: - @contextmanager - def open_wrapper(filename, mode): - file = open(filename, mode) - try: - yield file - finally: - file.close() + @contextmanager + def open_wrapper(filename, mode): + file = open(filename, mode) + try: + yield file + finally: + file.close() - This code is safe, as first part of generator (before yield) is - executed inside ``WITH_SETUP`` bytecode of caller + This code is safe, as the first part of the generator (before yield) + is executed inside the ``SETUP_WITH`` bytecode of the caller. Exception Propagation --------------------- -Sometimes ``finally`` block or ``__enter__/__exit__`` method can be -exited with an exception. Usually it's not a problem, since more -important exception like ``KeyboardInterrupt`` or ``SystemExit`` -should be thrown instead. But it may be nice to be able to keep -original exception inside a ``__context__`` attibute. So cleanup hook -signature may grow an exception argument:: +Sometimes a ``finally`` clause or an ``__enter__()``/``__exit__()`` +method can raise an exception. Usually this is not a problem, since +more important exceptions like ``KeyboardInterrupt`` or ``SystemExit`` +should be raised instead. But it may be nice to be able to keep the +original exception inside a ``__context__`` attribute. So the cleanup +hook signature may grow an exception argument:: - def sigint_handler(sig, frame) - if inspect.getcleanupframe(frame) is None: - raise KeyboardInterrupt() - sys.setcleanuphook(retry_sigint) + def sigint_handler(sig, frame) + if inspect.getcleanupframe(frame) is None: + raise KeyboardInterrupt() + sys.setcleanuphook(retry_sigint) - def retry_sigint(frame, exception=None): - if inspect.getcleanupframe(frame) is None: - raise KeyboardInterrupt() from exception + def retry_sigint(frame, exception=None): + if inspect.getcleanupframe(frame) is None: + raise KeyboardInterrupt() from exception .. note:: - No need to have three arguments like in ``__exit__`` method since - we have a ``__traceback__`` attribute in exception in Python 3.x + There is no need to have three arguments like in the ``__exit__`` + method since there is a ``__traceback__`` attribute in exception in + Python 3. -Although, this will set ``__cause__`` for the exception, which is not -exactly what's intended. So some hidden interpeter logic may be used -to put ``__context__`` attribute on every exception raised in cleanup -hook. +However, this will set the ``__cause__`` for the exception, which is +not exactly what's intended. So some hidden interpreter logic may be +used to put a ``__context__`` attribute on every exception raised in a +cleanup hook. Interruption Between Acquiring Resource and Try Block ----------------------------------------------------- -Example from the first section is not totally safe. Let's look closer:: +The example from the first section is not totally safe. Let's take a +closer look:: - lock.acquire() - try: - do_something() - finally: - lock.release() + lock.acquire() + try: + do_something() + finally: + lock.release() -There is no way it can be fixed without modifying the code. The actual -fix of this code depends very much on use case. +There is no way the code can be fixed unmodified. The actual fix +depends very much on the use case. Usually code can be fixed using a +``with`` statement:: -Usually code can be fixed using a ``with`` statement:: + with lock: + do_something() - with lock: - do_something() +However, for coroutines one usually can't use the ``with`` statement +because you need to ``yield`` for both the acquire and release +operations. So the code might be rewritten like this:: -Although, for coroutines you usually can't use ``with`` statement -because you need to ``yield`` for both aquire and release operations. -So code might be rewritten as following:: + try: + yield lock.acquire() + do_something() + finally: + yield lock.release() - try: - yield lock.acquire() - do_something() - finally: - yield lock.release() - -The actual lock code might need more code to support this use case, -but implementation is usually trivial, like check if lock has been -acquired and unlock if it is. +The actual locking code might need more code to support this use case, +but the implementation is usually trivial, like this: check if the +lock has been acquired and unlock if it is. Setting Interruption Context Inside Finally Itself -------------------------------------------------- Some coroutine libraries may need to set a timeout for the finally -clause itself. For example:: +clause itself. For example:: - try: - do_something() - finally: - with timeout(0.5): - try: - yield do_slow_cleanup() - finally: - yield do_fast_cleanup() + try: + do_something() + finally: + with timeout(0.5): + try: + yield do_slow_cleanup() + finally: + yield do_fast_cleanup() -With current semantics timeout will either protect -the whole ``with`` block or nothing at all, depending on the -implementation of a library. What the author is intended is to treat -``do_slow_cleanup`` as an ordinary code, and ``do_fast_cleanup`` as a -cleanup (non-interruptible one). +With current semantics, timeout will either protect the whole ``with`` +block or nothing at all, depending on the implementation of each +library. What the author intended is to treat ``do_slow_cleanup`` as +ordinary code, and ``do_fast_cleanup`` as a cleanup (a +non-interruptible one). -Similar case might occur when using greenlets or tasklets. +A similar case might occur when using greenlets or tasklets. This case can be fixed by exposing ``f_in_cleanup`` as a counter, and -by calling cleanup hook on each decrement. Corouting library may then -remember the value at timeout start, and compare it on each hook +by calling a cleanup hook on each decrement. A coroutine library may +then remember the value at timeout start, and compare it on each hook execution. -But in practice example is considered to be too obscure to take in -account. +But in practice, the example is considered to be too obscure to take +into account. Alternative Python Implementations Support ========================================== -We consider ``f_in_cleanup`` and implementation detail. The actual +We consider ``f_in_cleanup`` an implementation detail. The actual implementation may have some fake frame-like object passed to signal -handler, cleanup hook and returned from ``getcleanupframe``. The only -requirement is that ``inspect`` module functions work as expected on -that objects. For this reason we also allow to pass a ``generator`` -object to a ``isframeincleanup`` function, this disables need to use -``gi_frame`` attribute. +handler, cleanup hook and returned from ``getcleanupframe()``. The +only requirement is that the ``inspect`` module functions work as +expected on these objects. For this reason, we also allow to pass a +generator object to the ``isframeincleanup()`` function, which removes +the need to use the ``gi_frame`` attribute. -It may need to be specified that ``getcleanupframe`` must return the -same object that will be passed to cleanup hook at next invocation. +It might be necessary to specify that ``getcleanupframe()`` must +return the same object that will be passed to cleanup hook at the next +invocation. Alternative Names ================= -Original proposal had ``f_in_finally`` flag. The original intention -was to protect ``finally`` clauses. But as it grew up to protecting -``__enter__`` and ``__exit__`` methods too, the ``f_in_cleanup`` -method seems better. Although ``__enter__`` method is not a cleanup -routine, it at least relates to cleanup done by context managers. +The original proposal had a ``f_in_finally`` frame attribute, as the +original intention was to protect ``finally`` clauses. But as it grew +up to protecting ``__enter__`` and ``__exit__`` methods too, the +``f_in_cleanup`` name seems better. Although the ``__enter__`` method +is not a cleanup routine, it at least relates to cleanup done by +context managers. ``setcleanuphook``, ``isframeincleanup`` and ``getcleanupframe`` can be unobscured to ``set_cleanup_hook``, ``is_frame_in_cleanup`` and -``get_cleanup_frame``, althought they follow convention of their -respective modules. +``get_cleanup_frame``, although they follow the naming convention of +their respective modules. Alternative Proposals ===================== Propagating 'f_in_cleanup' Flag Automatically ------------------------------------------------ +--------------------------------------------- -This can make ``getcleanupframe`` unnecessary. But for yield based -coroutines you need to propagate it yourself. Making it writable leads -to somewhat unpredictable behavior of ``setcleanuphook`` +This can make ``getcleanupframe()`` unnecessary. But for yield-based +coroutines you need to propagate it yourself. Making it writable +leads to somewhat unpredictable behavior of ``setcleanuphook()``. Add Bytecodes 'INCR_CLEANUP', 'DECR_CLEANUP' -------------------------------------------- -These bytecodes can be used to protect expression inside ``with`` -statement, as well as making counter increments more explicit and easy -to debug (visible inside a disassembly). Some middle ground might be -chosen, like ``END_FINALLY`` and ``SETUP_WITH`` imlicitly decrements -counter (``END_FINALLY`` is present at end of ``with`` suite). +These bytecodes can be used to protect the expression inside the +``with`` statement, as well as making counter increments more explicit +and easy to debug (visible inside a disassembly). Some middle ground +might be chosen, like ``END_FINALLY`` and ``SETUP_WITH`` implicitly +decrementing the counter (``END_FINALLY`` is present at end of every +``with`` suite). -Although, adding new bytecodes must be considered very carefully. +However, adding new bytecodes must be considered very carefully. Expose 'f_in_cleanup' as a Counter ---------------------------------- -The original intention was to expose minimum needed functionality. -Although, as we consider frame flag ``f_in_cleanup`` as an -implementation detail, we may expose it as a counter. +The original intention was to expose a minimum of needed +functionality. However, as we consider the frame flag +``f_in_cleanup`` an implementation detail, we may expose it as a +counter. -Similarly, if we have a counter we may need to have cleanup hook -called on every counter decrement. It's unlikely have much performance -impact as nested finally clauses are unlikely common case. +Similarly, if we have a counter we may need to have the cleanup hook +called on every counter decrement. It's unlikely to have much +performance impact as nested finally clauses are an uncommon case. Add code object flag 'CO_CLEANUP' --------------------------------- -As an alternative to set flag inside ``WITH_SETUP``, and -``WITH_CLEANUP`` bytecodes we can introduce a flag ``CO_CLEANUP``. -When interpreter starts to execute code with ``CO_CLEANUP`` set, it -sets ``f_in_cleanup`` for the whole function body. This flag is set -for code object of ``__enter__`` and ``__exit__`` special methods. -Technically it might be set on functions called ``__enter__`` and -``__exit__``. +As an alternative to set the flag inside the ``SETUP_WITH`` and +``WITH_CLEANUP`` bytecodes, we can introduce a flag ``CO_CLEANUP``. +When the interpreter starts to execute code with ``CO_CLEANUP`` set, +it sets ``f_in_cleanup`` for the whole function body. This flag is +set for code objects of ``__enter__`` and ``__exit__`` special +methods. Technically it might be set on functions called +``__enter__`` and ``__exit__``. -This seems to be less clear solution. It also covers the case where -``__enter__`` and ``__exit__`` are called manually. This may be -accepted either as feature or as a unnecessary side-effect (unlikely -as a bug). +This seems to be less clear solution. It also covers the case where +``__enter__`` and ``__exit__`` are called manually. This may be +accepted either as a feature or as an unnecessary side-effect (or, +though unlikely, as a bug). It may also impose a problem when ``__enter__`` or ``__exit__`` -function are implemented in C, as there usually no frame to check for -``f_in_cleanup`` flag. +functions are implemented in C, as there is no code object to check +for the ``f_in_cleanup`` flag. Have Cleanup Callback on Frame Object Itself ----------------------------------------------- +-------------------------------------------- -Frame may be extended to have ``f_cleanup_callback`` which is called -when ``f_in_cleanup`` is reset to 0. It would help to register -different callbacks to different coroutines. +The frame object may be extended to have a ``f_cleanup_callback`` +member which is called when ``f_in_cleanup`` is reset to 0. This +would help to register different callbacks to different coroutines. -Despite apparent beauty. This solution doesn't add anything. As there -are two primary use cases: +Despite its apparent beauty, this solution doesn't add anything, as +the two primary use cases are: -* Set callback in signal handler. The callback is inherently single - one for this case +* Setting the callback in a signal handler. The callback is + inherently a single one for this case. -* Use single callback per loop for coroutine use case. And in almost - all cases there is only one loop per thread +* Use a single callback per loop for the coroutine use case. Here, in + almost all cases, there is only one loop per thread. No Cleanup Hook --------------- -Original proposal included no cleanup hook specification. As there are -few ways to achieve the same using current tools: +The original proposal included no cleanup hook specification, as there +are a few ways to achieve the same using current tools: -* Use ``sys.settrace`` and ``f_trace`` callback. It may impose some - problem to debugging, and has big performance impact (although, - interrupting doesn't happen very often) +* Using ``sys.settrace()`` and the ``f_trace`` callback. This may + impose some problem to debugging, and has a big performance impact + (although interrupting doesn't happen very often). -* Sleep a bit more and try again. For coroutine library it's easy. For - signals it may be achieved using ``alert``. +* Sleeping a bit more and trying again. For a coroutine library this + is easy. For signals it may be achieved using ``signal.alert``. Both methods are considered too impractical and a way to catch exit -from ``finally`` statement is proposed. +from ``finally`` clauses is proposed. References ========== .. [1] Monocle - https://github.com/saucelabs/monocle + https://github.com/saucelabs/monocle .. [2] Bluelet - https://github.com/sampsyo/bluelet + https://github.com/sampsyo/bluelet .. [3] Twisted: inlineCallbacks - http://twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.html + http://twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.html .. [4] Original discussion - http://mail.python.org/pipermail/python-ideas/2012-April/014705.html + http://mail.python.org/pipermail/python-ideas/2012-April/014705.html Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 8 02:51:40 2012 From: python-checkins at python.org (vinay.sajip) Date: Sun, 08 Apr 2012 02:51:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Added_multiproc?= =?utf8?q?essing_example_to_logging_cookbook=2E?= Message-ID: http://hg.python.org/cpython/rev/2908ed7335b0 changeset: 76159:2908ed7335b0 branch: 3.2 parent: 76153:7f123dec2731 user: Vinay Sajip date: Sun Apr 08 01:49:12 2012 +0100 summary: Added multiprocessing example to logging cookbook. files: Doc/howto/logging-cookbook.rst | 229 +++++++++++++++++++++ 1 files changed, 229 insertions(+), 0 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1315,3 +1315,232 @@ For more information about this configuration, you can see the `relevant section `_ of the Django documentation. + +A more elaborate multiprocessing example +---------------------------------------- + +The following working example shows how logging can be used with multiprocessing +using configuration files. The configurations are fairly simple, but serve to +illustrate how more complex ones could be implemented in a real multiprocessing +scenario. + +In the example, the main process spawns a listener process and some worker +processes. Each of the main process, the listener and the workers have three +separate configurations (the workers all share the same configuration). We can +see logging in the main process, how the workers log to a QueueHandler and how +the listener implements a QueueListener and a more complex logging +configuration, and arranges to dispatch events received via the queue to the +handlers specified in the configuration. Note that these configurations are +purely illustrative, but you should be able to adapt this example to your own +scenario. + +Here's the script - the docstrings and the comments hopefully explain how it +works:: + + import logging + import logging.config + import logging.handlers + from multiprocessing import Process, Queue, Event, current_process + import os + import random + import time + + class MyHandler(object): + """ + A simple handler for logging events. It runs in the listener process and + dispatches events to loggers based on the name in the received record, + which then get dispatched, by the logging system, to the handlers + configured for those records. + """ + def handle(self, record): + logger = logging.getLogger(record.name) + # The process name is transformed just to show that it's the listener + # doing the logging to files and console + record.processName = '%s (for %s)' % (current_process().name, record.processName) + logger.handle(record) + + def listener_process(q, stop_event, config): + """ + This could be done in the main process, but is just done in a separate + process for illustrative purposes. + + This initialises logging according to the specified configuration, + starts the listener and waits for the main process to signal completion + via the event. The listener is then stopped, and the process exits. + """ + logging.config.dictConfig(config) + listener = logging.handlers.QueueListener(q, MyHandler()) + listener.start() + if os.name == 'posix': + # On POSIX, the setup logger will have been configured in the + # parent process, but should have been disabled following the + # dictConfig call. + # On Windows, since fork isn't used, the setup logger won't + # exist in the child, so it would be created and the message + # would appear - hence the "if posix" clause. + logger = logging.getLogger('setup') + logger.critical('Should not appear, because of disabled logger ...') + stop_event.wait() + listener.stop() + + def worker_process(config): + """ + A number of these are spawned for the purpose of illustration. In + practice, they could be a heterogenous bunch of processes rather than + ones which are identical to each other. + + This initialises logging according to the specified configuration, + and logs a hundred messages with random levels to randomly selected + loggers. + + A small sleep is added to allow other processes a chance to run. This + is not strictly needed, but it mixes the output from the different + processes a bit more than if it's left out. + """ + logging.config.dictConfig(config) + levels = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, + logging.CRITICAL] + loggers = ['foo', 'foo.bar', 'foo.bar.baz', + 'spam', 'spam.ham', 'spam.ham.eggs'] + if os.name == 'posix': + # On POSIX, the setup logger will have been configured in the + # parent process, but should have been disabled following the + # dictConfig call. + # On Windows, since fork isn't used, the setup logger won't + # exist in the child, so it would be created and the message + # would appear - hence the "if posix" clause. + logger = logging.getLogger('setup') + logger.critical('Should not appear, because of disabled logger ...') + for i in range(100): + lvl = random.choice(levels) + logger = logging.getLogger(random.choice(loggers)) + logger.log(lvl, 'Message no. %d', i) + time.sleep(0.01) + + def main(): + q = Queue() + # The main process gets a simple configuration which prints to the console. + config_initial = { + 'version': 1, + 'formatters': { + 'detailed': { + 'class': 'logging.Formatter', + 'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s' + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'level': 'INFO', + }, + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['console'] + }, + } + # The worker process configuration is just a QueueHandler attached to the + # root logger, which allows all messages to be sent to the queue. + # We disable existing loggers to disable the "setup" logger used in the + # parent process. This is needed on POSIX because the logger will + # be there in the child following a fork(). + config_worker = { + 'version': 1, + 'disable_existing_loggers': True, + 'handlers': { + 'queue': { + 'class': 'logging.handlers.QueueHandler', + 'queue': q, + }, + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['queue'] + }, + } + # The listener process configuration shows that the full flexibility of + # logging configuration is available to dispatch events to handlers however + # you want. + # We disable existing loggers to disable the "setup" logger used in the + # parent process. This is needed on POSIX because the logger will + # be there in the child following a fork(). + config_listener = { + 'version': 1, + 'disable_existing_loggers': True, + 'formatters': { + 'detailed': { + 'class': 'logging.Formatter', + 'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s' + }, + 'simple': { + 'class': 'logging.Formatter', + 'format': '%(name)-15s %(levelname)-8s %(processName)-10s %(message)s' + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'level': 'INFO', + 'formatter': 'simple', + }, + 'file': { + 'class': 'logging.FileHandler', + 'filename': 'mplog.log', + 'mode': 'w', + 'formatter': 'detailed', + }, + 'foofile': { + 'class': 'logging.FileHandler', + 'filename': 'mplog-foo.log', + 'mode': 'w', + 'formatter': 'detailed', + }, + 'errors': { + 'class': 'logging.FileHandler', + 'filename': 'mplog-errors.log', + 'mode': 'w', + 'level': 'ERROR', + 'formatter': 'detailed', + }, + }, + 'loggers': { + 'foo': { + 'handlers' : ['foofile'] + } + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['console', 'file', 'errors'] + }, + } + # Log some initial events, just to show that logging in the parent works + # normally. + logging.config.dictConfig(config_initial) + logger = logging.getLogger('setup') + logger.info('About to create workers ...') + workers = [] + for i in range(5): + wp = Process(target=worker_process, name='worker %d' % (i + 1), + args=(config_worker,)) + workers.append(wp) + wp.start() + logger.info('Started worker: %s', wp.name) + logger.info('About to create listener ...') + stop_event = Event() + lp = Process(target=listener_process, name='listener', + args=(q, stop_event, config_listener)) + lp.start() + logger.info('Started listener') + # We now hang around for the workers to finish their work. + for wp in workers: + wp.join() + # Workers all done, listening can now stop. + # Logging in the parent still works normally. + logger.info('Telling listener to stop ...') + stop_event.set() + lp.join() + logger.info('All done.') + + if __name__ == '__main__': + main() + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 8 02:51:42 2012 From: python-checkins at python.org (vinay.sajip) Date: Sun, 08 Apr 2012 02:51:42 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merged_logging_cookbook_update_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/803f7a6090e7 changeset: 76160:803f7a6090e7 parent: 76158:f8a92fd084c2 parent: 76159:2908ed7335b0 user: Vinay Sajip date: Sun Apr 08 01:51:29 2012 +0100 summary: Merged logging cookbook update from 3.2. files: Doc/howto/logging-cookbook.rst | 228 +++++++++++++++++++++ 1 files changed, 228 insertions(+), 0 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1343,3 +1343,231 @@ "container" such as you?d find in an actual gzip file. This snippet is just for illustration purposes. +A more elaborate multiprocessing example +---------------------------------------- + +The following working example shows how logging can be used with multiprocessing +using configuration files. The configurations are fairly simple, but serve to +illustrate how more complex ones could be implemented in a real multiprocessing +scenario. + +In the example, the main process spawns a listener process and some worker +processes. Each of the main process, the listener and the workers have three +separate configurations (the workers all share the same configuration). We can +see logging in the main process, how the workers log to a QueueHandler and how +the listener implements a QueueListener and a more complex logging +configuration, and arranges to dispatch events received via the queue to the +handlers specified in the configuration. Note that these configurations are +purely illustrative, but you should be able to adapt this example to your own +scenario. + +Here's the script - the docstrings and the comments hopefully explain how it +works:: + + import logging + import logging.config + import logging.handlers + from multiprocessing import Process, Queue, Event, current_process + import os + import random + import time + + class MyHandler(object): + """ + A simple handler for logging events. It runs in the listener process and + dispatches events to loggers based on the name in the received record, + which then get dispatched, by the logging system, to the handlers + configured for those records. + """ + def handle(self, record): + logger = logging.getLogger(record.name) + # The process name is transformed just to show that it's the listener + # doing the logging to files and console + record.processName = '%s (for %s)' % (current_process().name, record.processName) + logger.handle(record) + + def listener_process(q, stop_event, config): + """ + This could be done in the main process, but is just done in a separate + process for illustrative purposes. + + This initialises logging according to the specified configuration, + starts the listener and waits for the main process to signal completion + via the event. The listener is then stopped, and the process exits. + """ + logging.config.dictConfig(config) + listener = logging.handlers.QueueListener(q, MyHandler()) + listener.start() + if os.name == 'posix': + # On POSIX, the setup logger will have been configured in the + # parent process, but should have been disabled following the + # dictConfig call. + # On Windows, since fork isn't used, the setup logger won't + # exist in the child, so it would be created and the message + # would appear - hence the "if posix" clause. + logger = logging.getLogger('setup') + logger.critical('Should not appear, because of disabled logger ...') + stop_event.wait() + listener.stop() + + def worker_process(config): + """ + A number of these are spawned for the purpose of illustration. In + practice, they could be a heterogenous bunch of processes rather than + ones which are identical to each other. + + This initialises logging according to the specified configuration, + and logs a hundred messages with random levels to randomly selected + loggers. + + A small sleep is added to allow other processes a chance to run. This + is not strictly needed, but it mixes the output from the different + processes a bit more than if it's left out. + """ + logging.config.dictConfig(config) + levels = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, + logging.CRITICAL] + loggers = ['foo', 'foo.bar', 'foo.bar.baz', + 'spam', 'spam.ham', 'spam.ham.eggs'] + if os.name == 'posix': + # On POSIX, the setup logger will have been configured in the + # parent process, but should have been disabled following the + # dictConfig call. + # On Windows, since fork isn't used, the setup logger won't + # exist in the child, so it would be created and the message + # would appear - hence the "if posix" clause. + logger = logging.getLogger('setup') + logger.critical('Should not appear, because of disabled logger ...') + for i in range(100): + lvl = random.choice(levels) + logger = logging.getLogger(random.choice(loggers)) + logger.log(lvl, 'Message no. %d', i) + time.sleep(0.01) + + def main(): + q = Queue() + # The main process gets a simple configuration which prints to the console. + config_initial = { + 'version': 1, + 'formatters': { + 'detailed': { + 'class': 'logging.Formatter', + 'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s' + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'level': 'INFO', + }, + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['console'] + }, + } + # The worker process configuration is just a QueueHandler attached to the + # root logger, which allows all messages to be sent to the queue. + # We disable existing loggers to disable the "setup" logger used in the + # parent process. This is needed on POSIX because the logger will + # be there in the child following a fork(). + config_worker = { + 'version': 1, + 'disable_existing_loggers': True, + 'handlers': { + 'queue': { + 'class': 'logging.handlers.QueueHandler', + 'queue': q, + }, + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['queue'] + }, + } + # The listener process configuration shows that the full flexibility of + # logging configuration is available to dispatch events to handlers however + # you want. + # We disable existing loggers to disable the "setup" logger used in the + # parent process. This is needed on POSIX because the logger will + # be there in the child following a fork(). + config_listener = { + 'version': 1, + 'disable_existing_loggers': True, + 'formatters': { + 'detailed': { + 'class': 'logging.Formatter', + 'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s' + }, + 'simple': { + 'class': 'logging.Formatter', + 'format': '%(name)-15s %(levelname)-8s %(processName)-10s %(message)s' + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'level': 'INFO', + 'formatter': 'simple', + }, + 'file': { + 'class': 'logging.FileHandler', + 'filename': 'mplog.log', + 'mode': 'w', + 'formatter': 'detailed', + }, + 'foofile': { + 'class': 'logging.FileHandler', + 'filename': 'mplog-foo.log', + 'mode': 'w', + 'formatter': 'detailed', + }, + 'errors': { + 'class': 'logging.FileHandler', + 'filename': 'mplog-errors.log', + 'mode': 'w', + 'level': 'ERROR', + 'formatter': 'detailed', + }, + }, + 'loggers': { + 'foo': { + 'handlers' : ['foofile'] + } + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['console', 'file', 'errors'] + }, + } + # Log some initial events, just to show that logging in the parent works + # normally. + logging.config.dictConfig(config_initial) + logger = logging.getLogger('setup') + logger.info('About to create workers ...') + workers = [] + for i in range(5): + wp = Process(target=worker_process, name='worker %d' % (i + 1), + args=(config_worker,)) + workers.append(wp) + wp.start() + logger.info('Started worker: %s', wp.name) + logger.info('About to create listener ...') + stop_event = Event() + lp = Process(target=listener_process, name='listener', + args=(q, stop_event, config_listener)) + lp.start() + logger.info('Started listener') + # We now hang around for the workers to finish their work. + for wp in workers: + wp.join() + # Workers all done, listening can now stop. + # Logging in the parent still works normally. + logger.info('Telling listener to stop ...') + stop_event.set() + lp.join() + logger.info('All done.') + + if __name__ == '__main__': + main() + -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Apr 8 05:36:27 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 08 Apr 2012 05:36:27 +0200 Subject: [Python-checkins] Daily reference leaks (803f7a6090e7): sum=0 Message-ID: results for 803f7a6090e7 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogSX1esp', '-x'] From python-checkins at python.org Sun Apr 8 15:57:23 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Sun, 08 Apr 2012 15:57:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Remove_unused_variable_from?= =?utf8?q?_gcmodule=2Ec=2E__The_code_no_longer_tests_for_the?= Message-ID: http://hg.python.org/cpython/rev/65fd991684fa changeset: 76161:65fd991684fa user: Kristj?n Valur J?nsson date: Sun Apr 08 13:56:25 2012 +0000 summary: Remove unused variable from gcmodule.c. The code no longer tests for the presence of a __del__ attribute on objects, rather it uses the tp_del slot. files: Modules/gcmodule.c | 9 --------- 1 files changed, 0 insertions(+), 9 deletions(-) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -65,9 +65,6 @@ /* Python string to use if unhandled exception occurs */ static PyObject *gc_str = NULL; -/* Python string used to look for __del__ attribute. */ -static PyObject *delstr = NULL; - /* This is the number of objects who survived the last full collection. It approximates the number of long lived objects tracked by the GC. @@ -802,12 +799,6 @@ PyGC_Head *gc; double t1 = 0.0; - if (delstr == NULL) { - delstr = PyUnicode_InternFromString("__del__"); - if (delstr == NULL) - Py_FatalError("gc couldn't allocate \"__del__\""); - } - if (debug & DEBUG_STATS) { PySys_WriteStderr("gc: collecting generation %d...\n", generation); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 8 22:18:47 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 08 Apr 2012 22:18:47 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_419=3A_Updates_from_Paul?= Message-ID: http://hg.python.org/peps/rev/a148d48aac4f changeset: 4205:a148d48aac4f user: Georg Brandl date: Sun Apr 08 22:18:51 2012 +0200 summary: PEP 419: Updates from Paul files: pep-0419.txt | 48 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 48 insertions(+), 0 deletions(-) diff --git a/pep-0419.txt b/pep-0419.txt --- a/pep-0419.txt +++ b/pep-0419.txt @@ -259,6 +259,10 @@ finally: lock.release() +The problem might occur if the code is interrupted just after +``lock.acquire()`` is executed but before the ``try`` block is +entered. + There is no way the code can be fixed unmodified. The actual fix depends very much on the use case. Usually code can be fixed using a ``with`` statement:: @@ -281,6 +285,32 @@ lock has been acquired and unlock if it is. +Handling EINTR Inside a Finally +------------------------------- + +Even if a signal handler is prepared to check the ``f_in_cleanup`` +flag, ``InterruptedError`` might be raised in the cleanup handler, +because the respective system call returned an ``EINTR`` error. The +primary use cases are prepared to handle this: + +* Posix mutexes never return ``EINTR`` + +* Networking libraries are always prepared to handle ``EINTR`` + +* Coroutine libraries are usually interrupted with the ``throw()`` + method, not with a signal + +The platform-specific function ``siginterrupt()`` might be used to +remove the need to handle ``EINTR``. However, it may have hardly +predictable consequences, for example ``SIGINT`` a handler is never +called if the main thread is stuck inside an IO routine. + +A better approach would be to have the code, which is usually used in +cleanup handlers, be prepared to handle ``InterruptedError`` +explicitly. An example of such code might be a file-based lock +implementation. + + Setting Interruption Context Inside Finally Itself -------------------------------------------------- @@ -313,6 +343,24 @@ into account. +Modifying KeyboardInterrupt +--------------------------- + +It should be decided if the default ``SIGINT`` handler should be +modified to use the described mechanism. The initial proposition is +to keep old behavior, for two reasons: + +* Most application do not care about cleanup on exit (either they do + not have external state, or they modify it in crash-safe way). + +* Cleanup may take too much time, not giving user a chance to + interrupt an application. + +The latter case can be fixed by allowing an unsafe break if a +``SIGINT`` handler is called twice, but it seems not worth the +complexity. + + Alternative Python Implementations Support ========================================== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 9 00:10:47 2012 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 9 Apr 2012 00:10:47 +0200 (CEST) Subject: [Python-checkins] r88935 - tracker/instances/python-dev/detectors/rietveldreactor.py Message-ID: <3VQpkH2cqrzMSG@mail.python.org> Author: martin.v.loewis Date: Mon Apr 9 00:10:47 2012 New Revision: 88935 Log: Issue 402: Update Django auth_user.username when Roundup _username changes. Modified: tracker/instances/python-dev/detectors/rietveldreactor.py Modified: tracker/instances/python-dev/detectors/rietveldreactor.py ============================================================================== --- tracker/instances/python-dev/detectors/rietveldreactor.py (original) +++ tracker/instances/python-dev/detectors/rietveldreactor.py Mon Apr 9 00:10:47 2012 @@ -15,6 +15,12 @@ "values(%s, %s, %s, '!', '', '', false, true, false, now(), now())", (nodeid, username, email)) +def update_django_user(db, cl, nodeid, oldvalues): + if 'username' in oldvalues: + newname = cl.get(nodeid, 'username') + c = db.cursor + c.execute("update auth_user set username=%s where id=%s", (newname, nodeid)) + def update_issue_cc(db, cl, nodeid, oldvalues): if 'nosy' not in oldvalues: return @@ -30,6 +36,7 @@ def init(db): db.user.react('create', create_django_user) + db.user.react('set', update_django_user) db.issue.react('set', update_issue_cc) # XXX react to email changes, roles # XXX react to subject, closed changes on issues From python-checkins at python.org Mon Apr 9 00:36:51 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 09 Apr 2012 00:36:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Make_test=5Fmai?= =?utf8?q?lbox_runnable_via_python_-m_unittest=2E?= Message-ID: http://hg.python.org/cpython/rev/fc1fa2b018e4 changeset: 76162:fc1fa2b018e4 branch: 3.2 parent: 76159:2908ed7335b0 user: R David Murray date: Sun Apr 08 16:46:18 2012 -0400 summary: Make test_mailbox runnable via python -m unittest. files: Lib/test/test_mailbox.py | 34 ++++++++++++++-------------- 1 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -20,7 +20,7 @@ pass -class TestBase(unittest.TestCase): +class TestBase: def _check_sample(self, msg): # Inspect a mailbox.Message representation of the sample message @@ -545,7 +545,7 @@ return self._path + '.lock' -class TestMailboxSuperclass(TestBase): +class TestMailboxSuperclass(TestBase, unittest.TestCase): def test_notimplemented(self): # Test that all Mailbox methods raise NotImplementedException. @@ -581,7 +581,7 @@ self.assertRaises(NotImplementedError, lambda: box.close()) -class TestMaildir(TestMailbox): +class TestMaildir(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.Maildir(path, factory) @@ -1043,7 +1043,7 @@ self._box.close() -class TestMbox(_TestMboxMMDF): +class TestMbox(_TestMboxMMDF, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.mbox(path, factory) @@ -1066,12 +1066,12 @@ perms = st.st_mode self.assertFalse((perms & 0o111)) # Execute bits should all be off. -class TestMMDF(_TestMboxMMDF): +class TestMMDF(_TestMboxMMDF, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.MMDF(path, factory) -class TestMH(TestMailbox): +class TestMH(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.MH(path, factory) @@ -1206,7 +1206,7 @@ return os.path.join(self._path, '.mh_sequences.lock') -class TestBabyl(TestMailbox): +class TestBabyl(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.Babyl(path, factory) @@ -1271,7 +1271,7 @@ self.assertTrue(box.files[i].closed) -class TestMessage(TestBase): +class TestMessage(TestBase, unittest.TestCase): _factory = mailbox.Message # Overridden by subclasses to reuse tests @@ -1351,7 +1351,7 @@ pass -class TestMaildirMessage(TestMessage): +class TestMaildirMessage(TestMessage, unittest.TestCase): _factory = mailbox.MaildirMessage @@ -1425,7 +1425,7 @@ self._check_sample(msg) -class _TestMboxMMDFMessage(TestMessage): +class _TestMboxMMDFMessage: _factory = mailbox._mboxMMDFMessage @@ -1472,12 +1472,12 @@ r"\d{2} \d{4}", msg.get_from()) is not None) -class TestMboxMessage(_TestMboxMMDFMessage): +class TestMboxMessage(_TestMboxMMDFMessage, TestMessage): _factory = mailbox.mboxMessage -class TestMHMessage(TestMessage): +class TestMHMessage(TestMessage, unittest.TestCase): _factory = mailbox.MHMessage @@ -1508,7 +1508,7 @@ self.assertEqual(msg.get_sequences(), ['foobar', 'replied']) -class TestBabylMessage(TestMessage): +class TestBabylMessage(TestMessage, unittest.TestCase): _factory = mailbox.BabylMessage @@ -1563,12 +1563,12 @@ self.assertEqual(visible[header], msg[header]) -class TestMMDFMessage(_TestMboxMMDFMessage): +class TestMMDFMessage(_TestMboxMMDFMessage, TestMessage): _factory = mailbox.MMDFMessage -class TestMessageConversion(TestBase): +class TestMessageConversion(TestBase, unittest.TestCase): def test_plain_to_x(self): # Convert Message to all formats @@ -1909,7 +1909,7 @@ self.assertTrue(proxy.closed) -class TestProxyFile(TestProxyFileBase): +class TestProxyFile(TestProxyFileBase, unittest.TestCase): def setUp(self): self._path = support.TESTFN @@ -1958,7 +1958,7 @@ self._test_close(mailbox._ProxyFile(self._file)) -class TestPartialFile(TestProxyFileBase): +class TestPartialFile(TestProxyFileBase, unittest.TestCase): def setUp(self): self._path = support.TESTFN -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 00:36:52 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 09 Apr 2012 00:36:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Make_test=5Fmai?= =?utf8?q?lbox_runnable_via_python_-m_unittest=2E?= Message-ID: http://hg.python.org/cpython/rev/96de17c95a7f changeset: 76163:96de17c95a7f branch: 2.7 parent: 76129:efeca6ff2751 user: R David Murray date: Sun Apr 08 18:34:36 2012 -0400 summary: Make test_mailbox runnable via python -m unittest. files: Lib/test/test_mailbox.py | 34 ++++++++++++++-------------- 1 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -20,7 +20,7 @@ # Silence Py3k warning rfc822 = test_support.import_module('rfc822', deprecated=True) -class TestBase(unittest.TestCase): +class TestBase: def _check_sample(self, msg): # Inspect a mailbox.Message representation of the sample message @@ -429,7 +429,7 @@ return self._path + '.lock' -class TestMailboxSuperclass(TestBase): +class TestMailboxSuperclass(TestBase, unittest.TestCase): def test_notimplemented(self): # Test that all Mailbox methods raise NotImplementedException. @@ -464,7 +464,7 @@ self.assertRaises(NotImplementedError, lambda: box.close()) -class TestMaildir(TestMailbox): +class TestMaildir(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.Maildir(path, factory) @@ -914,7 +914,7 @@ self._box.close() -class TestMbox(_TestMboxMMDF): +class TestMbox(_TestMboxMMDF, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.mbox(path, factory) @@ -937,12 +937,12 @@ perms = st.st_mode self.assertFalse((perms & 0111)) # Execute bits should all be off. -class TestMMDF(_TestMboxMMDF): +class TestMMDF(_TestMboxMMDF, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.MMDF(path, factory) -class TestMH(TestMailbox): +class TestMH(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.MH(path, factory) @@ -1074,7 +1074,7 @@ return os.path.join(self._path, '.mh_sequences.lock') -class TestBabyl(TestMailbox): +class TestBabyl(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.Babyl(path, factory) @@ -1103,7 +1103,7 @@ self.assertEqual(set(self._box.get_labels()), set(['blah'])) -class TestMessage(TestBase): +class TestMessage(TestBase, unittest.TestCase): _factory = mailbox.Message # Overridden by subclasses to reuse tests @@ -1174,7 +1174,7 @@ pass -class TestMaildirMessage(TestMessage): +class TestMaildirMessage(TestMessage, unittest.TestCase): _factory = mailbox.MaildirMessage @@ -1249,7 +1249,7 @@ self._check_sample(msg) -class _TestMboxMMDFMessage(TestMessage): +class _TestMboxMMDFMessage: _factory = mailbox._mboxMMDFMessage @@ -1296,12 +1296,12 @@ r"\d{2} \d{4}", msg.get_from())) -class TestMboxMessage(_TestMboxMMDFMessage): +class TestMboxMessage(_TestMboxMMDFMessage, TestMessage): _factory = mailbox.mboxMessage -class TestMHMessage(TestMessage): +class TestMHMessage(TestMessage, unittest.TestCase): _factory = mailbox.MHMessage @@ -1332,7 +1332,7 @@ self.assertEqual(msg.get_sequences(), ['foobar', 'replied']) -class TestBabylMessage(TestMessage): +class TestBabylMessage(TestMessage, unittest.TestCase): _factory = mailbox.BabylMessage @@ -1387,12 +1387,12 @@ self.assertEqual(visible[header], msg[header]) -class TestMMDFMessage(_TestMboxMMDFMessage): +class TestMMDFMessage(_TestMboxMMDFMessage, TestMessage): _factory = mailbox.MMDFMessage -class TestMessageConversion(TestBase): +class TestMessageConversion(TestBase, unittest.TestCase): def test_plain_to_x(self): # Convert Message to all formats @@ -1715,7 +1715,7 @@ proxy.close() -class TestProxyFile(TestProxyFileBase): +class TestProxyFile(TestProxyFileBase, unittest.TestCase): def setUp(self): self._path = test_support.TESTFN @@ -1764,7 +1764,7 @@ self._test_close(mailbox._ProxyFile(self._file)) -class TestPartialFile(TestProxyFileBase): +class TestPartialFile(TestProxyFileBase, unittest.TestCase): def setUp(self): self._path = test_support.TESTFN -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 00:36:52 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 09 Apr 2012 00:36:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge=3A_Make_test=5Fmailbox_runnable_via_python_-m_unittest?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/b58a11a5e0ab changeset: 76164:b58a11a5e0ab parent: 76161:65fd991684fa parent: 76162:fc1fa2b018e4 user: R David Murray date: Sun Apr 08 18:35:35 2012 -0400 summary: Merge: Make test_mailbox runnable via python -m unittest. files: Lib/test/test_mailbox.py | 34 ++++++++++++++-------------- 1 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -20,7 +20,7 @@ pass -class TestBase(unittest.TestCase): +class TestBase: def _check_sample(self, msg): # Inspect a mailbox.Message representation of the sample message @@ -545,7 +545,7 @@ return self._path + '.lock' -class TestMailboxSuperclass(TestBase): +class TestMailboxSuperclass(TestBase, unittest.TestCase): def test_notimplemented(self): # Test that all Mailbox methods raise NotImplementedException. @@ -581,7 +581,7 @@ self.assertRaises(NotImplementedError, lambda: box.close()) -class TestMaildir(TestMailbox): +class TestMaildir(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.Maildir(path, factory) @@ -1042,7 +1042,7 @@ self._box.close() -class TestMbox(_TestMboxMMDF): +class TestMbox(_TestMboxMMDF, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.mbox(path, factory) @@ -1065,12 +1065,12 @@ perms = st.st_mode self.assertFalse((perms & 0o111)) # Execute bits should all be off. -class TestMMDF(_TestMboxMMDF): +class TestMMDF(_TestMboxMMDF, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.MMDF(path, factory) -class TestMH(TestMailbox): +class TestMH(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.MH(path, factory) @@ -1205,7 +1205,7 @@ return os.path.join(self._path, '.mh_sequences.lock') -class TestBabyl(TestMailbox): +class TestBabyl(TestMailbox, unittest.TestCase): _factory = lambda self, path, factory=None: mailbox.Babyl(path, factory) @@ -1270,7 +1270,7 @@ self.assertTrue(box.files[i].closed) -class TestMessage(TestBase): +class TestMessage(TestBase, unittest.TestCase): _factory = mailbox.Message # Overridden by subclasses to reuse tests @@ -1350,7 +1350,7 @@ pass -class TestMaildirMessage(TestMessage): +class TestMaildirMessage(TestMessage, unittest.TestCase): _factory = mailbox.MaildirMessage @@ -1424,7 +1424,7 @@ self._check_sample(msg) -class _TestMboxMMDFMessage(TestMessage): +class _TestMboxMMDFMessage: _factory = mailbox._mboxMMDFMessage @@ -1471,12 +1471,12 @@ r"\d{2} \d{4}", msg.get_from()) is not None) -class TestMboxMessage(_TestMboxMMDFMessage): +class TestMboxMessage(_TestMboxMMDFMessage, TestMessage): _factory = mailbox.mboxMessage -class TestMHMessage(TestMessage): +class TestMHMessage(TestMessage, unittest.TestCase): _factory = mailbox.MHMessage @@ -1507,7 +1507,7 @@ self.assertEqual(msg.get_sequences(), ['foobar', 'replied']) -class TestBabylMessage(TestMessage): +class TestBabylMessage(TestMessage, unittest.TestCase): _factory = mailbox.BabylMessage @@ -1562,12 +1562,12 @@ self.assertEqual(visible[header], msg[header]) -class TestMMDFMessage(_TestMboxMMDFMessage): +class TestMMDFMessage(_TestMboxMMDFMessage, TestMessage): _factory = mailbox.MMDFMessage -class TestMessageConversion(TestBase): +class TestMessageConversion(TestBase, unittest.TestCase): def test_plain_to_x(self): # Convert Message to all formats @@ -1908,7 +1908,7 @@ self.assertTrue(proxy.closed) -class TestProxyFile(TestProxyFileBase): +class TestProxyFile(TestProxyFileBase, unittest.TestCase): def setUp(self): self._path = support.TESTFN @@ -1957,7 +1957,7 @@ self._test_close(mailbox._ProxyFile(self._file)) -class TestPartialFile(TestProxyFileBase): +class TestPartialFile(TestProxyFileBase, unittest.TestCase): def setUp(self): self._path = support.TESTFN -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 00:59:32 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 00:59:32 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzc5Nzg6?= =?utf8?q?_socketserver_now_restarts_the_select=28=29_call_when_EINTR_is_r?= =?utf8?q?eturned=2E?= Message-ID: http://hg.python.org/cpython/rev/5493d44b56d8 changeset: 76165:5493d44b56d8 branch: 3.2 parent: 76162:fc1fa2b018e4 user: Antoine Pitrou date: Mon Apr 09 00:47:24 2012 +0200 summary: Issue #7978: socketserver now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. Patch by Jerzy Kozera. files: Lib/socketserver.py | 15 ++++++++- Lib/test/test_socketserver.py | 34 +++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 ++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/Lib/socketserver.py b/Lib/socketserver.py --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -133,6 +133,7 @@ import select import sys import os +import errno try: import threading except ImportError: @@ -147,6 +148,15 @@ "ThreadingUnixStreamServer", "ThreadingUnixDatagramServer"]) +def _eintr_retry(func, *args): + """restart a system call interrupted by EINTR""" + while True: + try: + return func(*args) + except OSError as e: + if e.errno != errno.EINTR: + raise + class BaseServer: """Base class for server classes. @@ -222,7 +232,8 @@ # connecting to the socket to wake this up instead of # polling. Polling reduces our responsiveness to a # shutdown request and wastes cpu at all other times. - r, w, e = select.select([self], [], [], poll_interval) + r, w, e = _eintr_retry(select.select, [self], [], [], + poll_interval) if self in r: self._handle_request_noblock() finally: @@ -262,7 +273,7 @@ timeout = self.timeout elif self.timeout is not None: timeout = min(timeout, self.timeout) - fd_sets = select.select([self], [], [], timeout) + fd_sets = _eintr_retry(select.select, [self], [], [], timeout) if not fd_sets[0]: self.handle_timeout() return diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -8,6 +8,8 @@ import select import signal import socket +import select +import errno import tempfile import unittest import socketserver @@ -226,6 +228,38 @@ socketserver.DatagramRequestHandler, self.dgram_examine) + @contextlib.contextmanager + def mocked_select_module(self): + """Mocks the select.select() call to raise EINTR for first call""" + old_select = select.select + + class MockSelect: + def __init__(self): + self.called = 0 + + def __call__(self, *args): + self.called += 1 + if self.called == 1: + # raise the exception on first call + raise OSError(errno.EINTR, os.strerror(errno.EINTR)) + else: + # Return real select value for consecutive calls + return old_select(*args) + + select.select = MockSelect() + try: + yield select.select + finally: + select.select = old_select + + def test_InterruptServerSelectCall(self): + with self.mocked_select_module() as mock_select: + pid = self.run_server(socketserver.TCPServer, + socketserver.StreamRequestHandler, + self.stream_examine) + # Make sure select was called again: + self.assertGreater(mock_select.called, 1) + # Alas, on Linux (at least) recvfrom() doesn't return a meaningful # client address so this cannot work: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -510,6 +510,7 @@ Marko Kohtala Vlad Korolev Joseph Koshy +Jerzy Kozera Maksim Kozyarchuk Stefan Krah Bob Kras diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,10 @@ Library ------- +- Issue #7978: socketserver now restarts the select() call when EINTR is + returned. This avoids crashing the server loop when a signal is received. + Patch by Jerzy Kozera. + - Issue #14496: Fix wrong name in idlelib/tabbedpages.py. Patch by Popa Claudiu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 00:59:33 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 00:59:33 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=237978=3A_socketserver_now_restarts_the_select=28=29_?= =?utf8?q?call_when_EINTR_is_returned=2E?= Message-ID: http://hg.python.org/cpython/rev/97a0c6230ece changeset: 76166:97a0c6230ece parent: 76164:b58a11a5e0ab parent: 76165:5493d44b56d8 user: Antoine Pitrou date: Mon Apr 09 00:49:17 2012 +0200 summary: Issue #7978: socketserver now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. Patch by Jerzy Kozera. files: Lib/socketserver.py | 15 ++++++++- Lib/test/test_socketserver.py | 34 +++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 ++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/Lib/socketserver.py b/Lib/socketserver.py --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -133,6 +133,7 @@ import select import sys import os +import errno try: import threading except ImportError: @@ -147,6 +148,15 @@ "ThreadingUnixStreamServer", "ThreadingUnixDatagramServer"]) +def _eintr_retry(func, *args): + """restart a system call interrupted by EINTR""" + while True: + try: + return func(*args) + except OSError as e: + if e.errno != errno.EINTR: + raise + class BaseServer: """Base class for server classes. @@ -223,7 +233,8 @@ # connecting to the socket to wake this up instead of # polling. Polling reduces our responsiveness to a # shutdown request and wastes cpu at all other times. - r, w, e = select.select([self], [], [], poll_interval) + r, w, e = _eintr_retry(select.select, [self], [], [], + poll_interval) if self in r: self._handle_request_noblock() @@ -273,7 +284,7 @@ timeout = self.timeout elif self.timeout is not None: timeout = min(timeout, self.timeout) - fd_sets = select.select([self], [], [], timeout) + fd_sets = _eintr_retry(select.select, [self], [], [], timeout) if not fd_sets[0]: self.handle_timeout() return diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -8,6 +8,8 @@ import select import signal import socket +import select +import errno import tempfile import unittest import socketserver @@ -226,6 +228,38 @@ socketserver.DatagramRequestHandler, self.dgram_examine) + @contextlib.contextmanager + def mocked_select_module(self): + """Mocks the select.select() call to raise EINTR for first call""" + old_select = select.select + + class MockSelect: + def __init__(self): + self.called = 0 + + def __call__(self, *args): + self.called += 1 + if self.called == 1: + # raise the exception on first call + raise OSError(errno.EINTR, os.strerror(errno.EINTR)) + else: + # Return real select value for consecutive calls + return old_select(*args) + + select.select = MockSelect() + try: + yield select.select + finally: + select.select = old_select + + def test_InterruptServerSelectCall(self): + with self.mocked_select_module() as mock_select: + pid = self.run_server(socketserver.TCPServer, + socketserver.StreamRequestHandler, + self.stream_examine) + # Make sure select was called again: + self.assertGreater(mock_select.called, 1) + # Alas, on Linux (at least) recvfrom() doesn't return a meaningful # client address so this cannot work: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -559,6 +559,7 @@ Arkady Koplyarov Vlad Korolev Joseph Koshy +Jerzy Kozera Maksim Kozyarchuk Stefan Krah Bob Kras diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #7978: socketserver now restarts the select() call when EINTR is + returned. This avoids crashing the server loop when a signal is received. + Patch by Jerzy Kozera. + - Issue #14522: Avoid duplicating socket handles in multiprocessing.connection. Patch by sbt. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 01:12:45 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 01:12:45 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzc5Nzg6?= =?utf8?q?_socketserver_now_restarts_the_select=28=29_call_when_EINTR_is_r?= =?utf8?q?eturned=2E?= Message-ID: http://hg.python.org/cpython/rev/d941d1fcc6e6 changeset: 76167:d941d1fcc6e6 branch: 2.7 parent: 76163:96de17c95a7f user: Antoine Pitrou date: Mon Apr 09 00:47:24 2012 +0200 summary: Issue #7978: socketserver now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. Patch by Jerzy Kozera. files: Lib/SocketServer.py | 15 ++++++++- Lib/test/test_socketserver.py | 34 +++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 ++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/Lib/SocketServer.py b/Lib/SocketServer.py --- a/Lib/SocketServer.py +++ b/Lib/SocketServer.py @@ -133,6 +133,7 @@ import select import sys import os +import errno try: import threading except ImportError: @@ -147,6 +148,15 @@ "ThreadingUnixStreamServer", "ThreadingUnixDatagramServer"]) +def _eintr_retry(func, *args): + """restart a system call interrupted by EINTR""" + while True: + try: + return func(*args) + except OSError as e: + if e.errno != errno.EINTR: + raise + class BaseServer: """Base class for server classes. @@ -222,7 +232,8 @@ # connecting to the socket to wake this up instead of # polling. Polling reduces our responsiveness to a # shutdown request and wastes cpu at all other times. - r, w, e = select.select([self], [], [], poll_interval) + r, w, e = _eintr_retry(select.select, [self], [], [], + poll_interval) if self in r: self._handle_request_noblock() finally: @@ -262,7 +273,7 @@ timeout = self.timeout elif self.timeout is not None: timeout = min(timeout, self.timeout) - fd_sets = select.select([self], [], [], timeout) + fd_sets = _eintr_retry(select.select, [self], [], [], timeout) if not fd_sets[0]: self.handle_timeout() return diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -8,6 +8,8 @@ import select import signal import socket +import select +import errno import tempfile import unittest import SocketServer @@ -225,6 +227,38 @@ SocketServer.DatagramRequestHandler, self.dgram_examine) + @contextlib.contextmanager + def mocked_select_module(self): + """Mocks the select.select() call to raise EINTR for first call""" + old_select = select.select + + class MockSelect: + def __init__(self): + self.called = 0 + + def __call__(self, *args): + self.called += 1 + if self.called == 1: + # raise the exception on first call + raise OSError(errno.EINTR, os.strerror(errno.EINTR)) + else: + # Return real select value for consecutive calls + return old_select(*args) + + select.select = MockSelect() + try: + yield select.select + finally: + select.select = old_select + + def test_InterruptServerSelectCall(self): + with self.mocked_select_module() as mock_select: + pid = self.run_server(SocketServer.TCPServer, + SocketServer.StreamRequestHandler, + self.stream_examine) + # Make sure select was called again: + self.assertGreater(mock_select.called, 1) + # Alas, on Linux (at least) recvfrom() doesn't return a meaningful # client address so this cannot work: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -461,6 +461,7 @@ Damon Kohler Marko Kohtala Joseph Koshy +Jerzy Kozera Maksim Kozyarchuk Stefan Krah Bob Kras diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -44,6 +44,10 @@ Library ------- +- Issue #7978: SocketServer now restarts the select() call when EINTR is + returned. This avoids crashing the server loop when a signal is received. + Patch by Jerzy Kozera. + - Issue #14409: IDLE now properly executes commands in the Shell window when it cannot read the normal config files on startup and has to use the built-in default key bindings. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 01:23:44 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 01:23:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Fix_flakiness_i?= =?utf8?q?n_test=5Fsocketserver?= Message-ID: http://hg.python.org/cpython/rev/463fd270c5de changeset: 76168:463fd270c5de branch: 2.7 user: Antoine Pitrou date: Mon Apr 09 01:15:06 2012 +0200 summary: Fix flakiness in test_socketserver files: Lib/test/test_socketserver.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -34,8 +34,11 @@ if hasattr(signal, 'alarm'): signal.alarm(n) +# Remember real select() to avoid interferences with mocking +_real_select = select.select + def receive(sock, n, timeout=20): - r, w, x = select.select([sock], [], [], timeout) + r, w, x = _real_select([sock], [], [], timeout) if sock in r: return sock.recv(n) else: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 01:23:45 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 01:23:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Fix_flakiness_i?= =?utf8?q?n_test=5Fsocketserver?= Message-ID: http://hg.python.org/cpython/rev/4f5b44de5c37 changeset: 76169:4f5b44de5c37 branch: 3.2 parent: 76165:5493d44b56d8 user: Antoine Pitrou date: Mon Apr 09 01:16:47 2012 +0200 summary: Fix flakiness in test_socketserver files: Lib/test/test_socketserver.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -34,8 +34,11 @@ if hasattr(signal, 'alarm'): signal.alarm(n) +# Remember real select() to avoid interferences with mocking +_real_select = select.select + def receive(sock, n, timeout=20): - r, w, x = select.select([sock], [], [], timeout) + r, w, x = _real_select([sock], [], [], timeout) if sock in r: return sock.recv(n) else: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 01:23:45 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 01:23:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Fix_flakiness_in_test=5Fsocketserver?= Message-ID: http://hg.python.org/cpython/rev/12984b151204 changeset: 76170:12984b151204 parent: 76166:97a0c6230ece parent: 76169:4f5b44de5c37 user: Antoine Pitrou date: Mon Apr 09 01:18:07 2012 +0200 summary: Fix flakiness in test_socketserver files: Lib/test/test_socketserver.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -34,8 +34,11 @@ if hasattr(signal, 'alarm'): signal.alarm(n) +# Remember real select() to avoid interferences with mocking +_real_select = select.select + def receive(sock, n, timeout=20): - r, w, x = select.select([sock], [], [], timeout) + r, w, x = _real_select([sock], [], [], timeout) if sock in r: return sock.recv(n) else: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 01:32:07 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 09 Apr 2012 01:32:07 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_add_info_on_functio?= =?utf8?q?ns_to_sleep?= Message-ID: http://hg.python.org/peps/rev/0321e33832ef changeset: 4206:0321e33832ef user: Victor Stinner date: Mon Apr 09 01:32:02 2012 +0200 summary: PEP 418: add info on functions to sleep files: pep-0418.txt | 134 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 134 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -139,6 +139,53 @@ running for more than 49 days. +time.sleep() +------------ + +Suspend execution for the given number of seconds. The actual suspension time +may be less than that requested because any caught signal will terminate the +time.sleep() following execution of that signal's catching routine. Also, the +suspension time may be longer than requested by an arbitrary amount because of +the scheduling of other activity in the system. + +Pseudo-code [#pseudo]_:: + + try: + import select + except ImportError: + has_select = False + else: + has_select = hasattr(select, "select") + + if has_select: + def sleep(seconds): + return select.select([], [], [], seconds) + + elif hasattr(_time, "delay"): + def sleep(seconds): + milliseconds = int(seconds * 1000) + _time.delay(milliseconds) + + elif os.name == "nt": + def sleep(seconds): + milliseconds = int(seconds * 1000) + win32api.ResetEvent(hInterruptEvent); + win32api.WaitForSingleObject(sleep.sigint_event, milliseconds) + + sleep.sigint_event = win32api.CreateEvent(NULL, TRUE, FALSE, FALSE) + # SetEvent(sleep.sigint_event) will be called by the signal handler of SIGINT + + elif os.name == "os2": + def sleep(seconds): + milliseconds = int(seconds * 1000) + DosSleep(milliseconds) + + else: + def sleep(seconds): + seconds = int(seconds) + _time.sleep(seconds) + + time.get_clock_info(name) ------------------------- @@ -734,6 +781,93 @@ "overview of time and timers". +Sleeping +======== + +Sleep can be interrupted by a signal: the function fails with EINTR. + +======================== ========== +Name Resolution +======================== ========== +nanosleep() 1 ns +clock_nanosleep() 1 ns +usleep() 1 ?s +delay() 1 ?s +sleep() 1 sec +======================== ========== + +Other functions: + +======================== ========== +Name Resolution +======================== ========== +sigtimedwait() 1 ns +pthread_cond_timedwait() 1 ns +sem_timedwait() 1 ns +select() 1 ?s +epoll() 1 ms +poll() 1 ms +WaitForSingleObject() 1 ms +======================== ========== + +Classic functions +----------------- + + * sleep(seconds) + * usleep(microseconds) + * nanosleep(nanoseconds, remaining) + `Linux manpage + `_ + * delay(milliseconds) + +clock_nanosleep +--------------- + +clock_nanosleep(clock_id, flags, nanoseconds, remaining): +`Linux manpage +`_. + +If flags is TIMER_ABSTIME, then request is interpreted as an absolute +time as measured by the clock, clock_id. If request is less than or +equal to the current value of the clock, then clock_nanosleep() returns +immediately without suspending the calling thread. + +POSIX.1 specifies that changing the value of the CLOCK_REALTIME clock via +clock_settime(2) shall have no effect on a thread that is blocked on a relative +clock_nanosleep(). + +select() +-------- + +select(nfds, readfds, writefds, exceptfs, timeout). + +Since Linux 2.6.28, select() uses high-resolution timers to handle the timeout. +A process has a "slack" attribute to configure the accuracy of the timeout, the +default slack is 50 microseconds. Before Linux 2.6.28, timeouts for select() +were handled by the main timing subsystem at a jiffy-level resolution. Read +also `High- (but not too high-) resolution timeouts +`_ and `Timer slack +`_. + + +Other functions +--------------- + + * poll(), epoll() + * sigtimedwait(). POSIX: "If the Monotonic Clock option is supported, the + CLOCK_MONOTONIC clock shall be used to measure the time interval specified + by the timeout argument." + * pthread_cond_timedwait(), pthread_condattr_setclock(). "The default value of + the clock attribute shall refer to the system clock." + * sem_timedwait(): "If the Timers option is supported, the timeout shall be + based on the CLOCK_REALTIME clock. If the Timers option is not supported, + the timeout shall be based on the system clock as returned by the time() + function. The resolution of the timeout shall be the resolution of the clock + on which it is based." + * WaitForSingleObject(): use the same timer than GetTickCount() with the same + resolution. + + Alternatives: API design ======================== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 9 01:47:12 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 01:47:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Fix_the_patch_f?= =?utf8?q?or_issue_=237978=3A_select=28=29_raises_select=2Eerror_before_3?= =?utf8?q?=2E3=2C_not?= Message-ID: http://hg.python.org/cpython/rev/f8e7fcd581ff changeset: 76171:f8e7fcd581ff branch: 3.2 parent: 76169:4f5b44de5c37 user: Antoine Pitrou date: Mon Apr 09 01:37:19 2012 +0200 summary: Fix the patch for issue #7978: select() raises select.error before 3.3, not OSError. files: Lib/socketserver.py | 4 ++-- Lib/test/test_socketserver.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/socketserver.py b/Lib/socketserver.py --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -153,8 +153,8 @@ while True: try: return func(*args) - except OSError as e: - if e.errno != errno.EINTR: + except (OSError, select.error) as e: + if e.args[0] != errno.EINTR: raise class BaseServer: diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -244,7 +244,7 @@ self.called += 1 if self.called == 1: # raise the exception on first call - raise OSError(errno.EINTR, os.strerror(errno.EINTR)) + raise select.error(errno.EINTR, os.strerror(errno.EINTR)) else: # Return real select value for consecutive calls return old_select(*args) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 01:47:13 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 01:47:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Null_merge?= Message-ID: http://hg.python.org/cpython/rev/fbfb1e7738b7 changeset: 76172:fbfb1e7738b7 parent: 76170:12984b151204 parent: 76171:f8e7fcd581ff user: Antoine Pitrou date: Mon Apr 09 01:41:00 2012 +0200 summary: Null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 01:47:13 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 01:47:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Fix_the_patch_f?= =?utf8?q?or_issue_=237978=3A_select=28=29_raises_select=2Eerror_before_3?= =?utf8?q?=2E3=2C_not?= Message-ID: http://hg.python.org/cpython/rev/4298d6e79ecb changeset: 76173:4298d6e79ecb branch: 2.7 parent: 76168:463fd270c5de user: Antoine Pitrou date: Mon Apr 09 01:41:34 2012 +0200 summary: Fix the patch for issue #7978: select() raises select.error before 3.3, not OSError. files: Lib/SocketServer.py | 4 ++-- Lib/test/test_socketserver.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/SocketServer.py b/Lib/SocketServer.py --- a/Lib/SocketServer.py +++ b/Lib/SocketServer.py @@ -153,8 +153,8 @@ while True: try: return func(*args) - except OSError as e: - if e.errno != errno.EINTR: + except (OSError, select.error) as e: + if e.args[0] != errno.EINTR: raise class BaseServer: diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -243,7 +243,7 @@ self.called += 1 if self.called == 1: # raise the exception on first call - raise OSError(errno.EINTR, os.strerror(errno.EINTR)) + raise select.error(errno.EINTR, os.strerror(errno.EINTR)) else: # Return real select value for consecutive calls return old_select(*args) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 02:24:42 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 09 Apr 2012 02:24:42 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Make_it_explicit_th?= =?utf8?q?an_calling_timeBeginPeriod=28=29_affects?= Message-ID: http://hg.python.org/peps/rev/7a9076f40577 changeset: 4207:7a9076f40577 user: Victor Stinner date: Mon Apr 09 02:24:38 2012 +0200 summary: PEP 418: Make it explicit than calling timeBeginPeriod() affects WaitForSingleObject() and Sleep() files: pep-0418.txt | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -509,9 +509,10 @@ The default precision of the timeGetTime function can be five milliseconds or more, depending on the machine. -timeBeginPeriod() can be used to increase the precision of -timeGetTime() up to 1 millisecond, but it negatively affects power -consumption. +timeBeginPeriod() can be used to increase the precision of timeGetTime() up to +1 millisecond, but it negatively affects power consumption. Calling +timeBeginPeriod() also affects the granularity of some other timing calls, such +as CreateWaitableTimer(), WaitForSingleObject() and Sleep(). .. note:: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 9 04:36:38 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 09 Apr 2012 04:36:38 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Remove_redundancy_in_listin?= =?utf8?q?g_of_all_mailbox_classes_in_test=5Fmailbox=2E?= Message-ID: http://hg.python.org/cpython/rev/52f6a0c6093e changeset: 76174:52f6a0c6093e parent: 76172:fbfb1e7738b7 user: R David Murray date: Sun Apr 08 21:00:27 2012 -0400 summary: Remove redundancy in listing of all mailbox classes in test_mailbox. files: Lib/test/test_mailbox.py | 24 +++++++++--------------- 1 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -22,6 +22,10 @@ class TestBase: + all_mailbox_types = (mailbox.Message, mailbox.MaildirMessage, + mailbox.mboxMessage, mailbox.MHMessage, + mailbox.BabylMessage, mailbox.MMDFMessage) + def _check_sample(self, msg): # Inspect a mailbox.Message representation of the sample message self.assertIsInstance(msg, email.message.Message) @@ -1337,9 +1341,7 @@ # Copy self's format-specific data to other message formats. # This test is superficial; better ones are in TestMessageConversion. msg = self._factory() - for class_ in (mailbox.Message, mailbox.MaildirMessage, - mailbox.mboxMessage, mailbox.MHMessage, - mailbox.BabylMessage, mailbox.MMDFMessage): + for class_ in self.all_mailbox_types: other_msg = class_() msg._explain_to(other_msg) other_msg = email.message.Message() @@ -1571,35 +1573,27 @@ def test_plain_to_x(self): # Convert Message to all formats - for class_ in (mailbox.Message, mailbox.MaildirMessage, - mailbox.mboxMessage, mailbox.MHMessage, - mailbox.BabylMessage, mailbox.MMDFMessage): + for class_ in self.all_mailbox_types: msg_plain = mailbox.Message(_sample_message) msg = class_(msg_plain) self._check_sample(msg) def test_x_to_plain(self): # Convert all formats to Message - for class_ in (mailbox.Message, mailbox.MaildirMessage, - mailbox.mboxMessage, mailbox.MHMessage, - mailbox.BabylMessage, mailbox.MMDFMessage): + for class_ in self.all_mailbox_types: msg = class_(_sample_message) msg_plain = mailbox.Message(msg) self._check_sample(msg_plain) def test_x_from_bytes(self): # Convert all formats to Message - for class_ in (mailbox.Message, mailbox.MaildirMessage, - mailbox.mboxMessage, mailbox.MHMessage, - mailbox.BabylMessage, mailbox.MMDFMessage): + for class_ in self.all_mailbox_types: msg = class_(_bytes_sample_message) self._check_sample(msg) def test_x_to_invalid(self): # Convert all formats to an invalid format - for class_ in (mailbox.Message, mailbox.MaildirMessage, - mailbox.mboxMessage, mailbox.MHMessage, - mailbox.BabylMessage, mailbox.MMDFMessage): + for class_ in self.all_mailbox_types: self.assertRaises(TypeError, lambda: class_(False)) def test_maildir_to_maildir(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 04:36:39 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 09 Apr 2012 04:36:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_=2312537=3A_in_mailbox_avoi?= =?utf8?q?d_depending_on_knowledge_of_email_package_internals?= Message-ID: http://hg.python.org/cpython/rev/5c1c402a63e5 changeset: 76175:5c1c402a63e5 user: R David Murray date: Sun Apr 08 22:36:07 2012 -0400 summary: #12537: in mailbox avoid depending on knowledge of email package internals Previously mailbox was copying a list of attributes from one message object to another in order to "copy the message data". This means that any time new attributes were added to email.message.Message, mailbox broke. Now instead it copies all attributes from the source object to the target object, skipping any mailbox-object-specific attributes to produce the same clean initial state it was previously getting by copying only the "known" attributes. David Lam assisted in the development of this patch. files: Lib/mailbox.py | 15 ++++++++++++--- Lib/test/test_mailbox.py | 23 +++++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Lib/mailbox.py b/Lib/mailbox.py --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -1462,9 +1462,10 @@ def _become_message(self, message): """Assume the non-format-specific state of message.""" - for name in ('_headers', '_unixfrom', '_payload', '_charset', - 'preamble', 'epilogue', 'defects', '_default_type'): - self.__dict__[name] = message.__dict__[name] + type_specific = getattr(message, '_type_specific_attributes', []) + for name in message.__dict__: + if name not in type_specific: + self.__dict__[name] = message.__dict__[name] def _explain_to(self, message): """Copy format-specific state to message insofar as possible.""" @@ -1477,6 +1478,8 @@ class MaildirMessage(Message): """Message with Maildir-specific properties.""" + _type_specific_attributes = ['_subdir', '_info', '_date'] + def __init__(self, message=None): """Initialize a MaildirMessage instance.""" self._subdir = 'new' @@ -1584,6 +1587,8 @@ class _mboxMMDFMessage(Message): """Message with mbox- or MMDF-specific properties.""" + _type_specific_attributes = ['_from'] + def __init__(self, message=None): """Initialize an mboxMMDFMessage instance.""" self.set_from('MAILER-DAEMON', True) @@ -1699,6 +1704,8 @@ class MHMessage(Message): """Message with MH-specific properties.""" + _type_specific_attributes = ['_sequences'] + def __init__(self, message=None): """Initialize an MHMessage instance.""" self._sequences = [] @@ -1769,6 +1776,8 @@ class BabylMessage(Message): """Message with Babyl-specific properties.""" + _type_specific_attributes = ['_labels', '_visible'] + def __init__(self, message=None): """Initialize an BabylMessage instance.""" self._labels = [] diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -1330,6 +1330,14 @@ # Initialize with invalid argument self.assertRaises(TypeError, lambda: self._factory(object())) + def test_all_eMM_attribues_exist(self): + # Issue 12537 + eMM = email.message_from_string(_sample_message) + msg = self._factory(_sample_message) + for attr in eMM.__dict__: + self.assertTrue(attr in msg.__dict__, + '{} attribute does not exist'.format(attr)) + def test_become_message(self): # Take on the state of another message eMM = email.message_from_string(_sample_message) @@ -1596,6 +1604,21 @@ for class_ in self.all_mailbox_types: self.assertRaises(TypeError, lambda: class_(False)) + def test_type_specific_attributes_removed_on_conversion(self): + reference = {class_: class_(_sample_message).__dict__ + for class_ in self.all_mailbox_types} + for class1 in self.all_mailbox_types: + for class2 in self.all_mailbox_types: + if class1 is class2: + continue + source = class1(_sample_message) + target = class2(source) + type_specific = [a for a in reference[class1] + if a not in reference[class2]] + for attr in type_specific: + self.assertNotIn(attr, target.__dict__, + "while converting {} to {}".format(class1, class2)) + def test_maildir_to_maildir(self): # Convert MaildirMessage to MaildirMessage msg_maildir = mailbox.MaildirMessage(_sample_message) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #12537: The mailbox module no longer depends on knowledge of internal + implementation details of the email package Message object. + - Issue #7978: socketserver now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. Patch by Jerzy Kozera. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Apr 9 05:36:24 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 09 Apr 2012 05:36:24 +0200 Subject: [Python-checkins] Daily reference leaks (fbfb1e7738b7): sum=0 Message-ID: results for fbfb1e7738b7 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogNmZlF8', '-x'] From python-checkins at python.org Mon Apr 9 08:59:26 2012 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 9 Apr 2012 08:59:26 +0200 (CEST) Subject: [Python-checkins] r88936 - tracker/instances/python-dev/scripts/update_email.py Message-ID: <3VR2SG6BpRzMYc@mail.python.org> Author: martin.v.loewis Date: Mon Apr 9 08:59:26 2012 New Revision: 88936 Log: Add script to synchronize email addresses with Rietveld Added: tracker/instances/python-dev/scripts/update_email.py (contents, props changed) Added: tracker/instances/python-dev/scripts/update_email.py ============================================================================== --- (empty file) +++ tracker/instances/python-dev/scripts/update_email.py Mon Apr 9 08:59:26 2012 @@ -0,0 +1,46 @@ +#!/usr/bin/python +# cron job to update rietveld tables when the email address changes +# this updates auth_user.email, codereview_account.email +# and codereview_issue.cc, based on the nosy list s +# it does not update codereview_issue.reviewers, since it would be +# too expensive to search all issues, and since the reviewers list +# is something that has to be filled out separately in Rietveld. +# It also does not update codereview_message, since these have already +# been sent with the email addresses recorded in the database. +import sys, os, base64, cPickle +sys.path.insert(1,'/home/roundup/roundup/lib/python2.5/site-packages') +import roundup.instance + +verbose = sys.argv[1:] == ['-v'] + +homedir = os.path.join(os.path.dirname(__file__), "..") +tracker = roundup.instance.open(homedir) +db = tracker.open('admin') +c = db.cursor + +c.execute('select a.id, b.email, a._address from _user a, auth_user b ' + 'where a.id=b.id and a._address != b.email') +for user, old, new in c.fetchall(): + old = old.decode('ascii') + new = new.decode('ascii') + if verbose: + print "Update user", user, 'from', old, 'to ', new + c.execute('update auth_user set email=%s where id=%s', (new, user)) + c.execute('update codereview_account set email=%s where id=%s', (new, user)) + # find issues where user is on nosy + c.execute('select nodeid,cc from issue_nosy, codereview_issue ' + 'where linkid=%s and nodeid=id', (user,)) + for nodeid, cc in c.fetchall(): + cc = cPickle.loads(base64.decodestring(cc)) + if verbose: + print " Update issue", nodeid, cc + try: + cc[cc.index(old)] = new + except ValueError: + cc.append(new) + cc = base64.encodestring(cPickle.dumps(cc)) + c.execute('update codereview_issue set cc=%s where id=%s', (cc, nodeid)) + + db.conn.commit() + + From python-checkins at python.org Mon Apr 9 09:08:43 2012 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 9 Apr 2012 09:08:43 +0200 (CEST) Subject: [Python-checkins] r88937 - in tracker/instances/python-dev: detectors/rietveldreactor.py scripts/update_email.py Message-ID: <3VR2fz3WQ1zMD7@mail.python.org> Author: martin.v.loewis Date: Mon Apr 9 09:08:43 2012 New Revision: 88937 Log: Move email updating to reactor. Modified: tracker/instances/python-dev/detectors/rietveldreactor.py tracker/instances/python-dev/scripts/update_email.py Modified: tracker/instances/python-dev/detectors/rietveldreactor.py ============================================================================== --- tracker/instances/python-dev/detectors/rietveldreactor.py (original) +++ tracker/instances/python-dev/detectors/rietveldreactor.py Mon Apr 9 09:08:43 2012 @@ -16,10 +16,30 @@ (nodeid, username, email)) def update_django_user(db, cl, nodeid, oldvalues): + user = nodeid if 'username' in oldvalues: newname = cl.get(nodeid, 'username') c = db.cursor - c.execute("update auth_user set username=%s where id=%s", (newname, nodeid)) + c.execute("update auth_user set username=%s where id=%s", (newname, user)) + + if 'address' in oldvalues: + old = oldvalues['address'].decode('ascii') + new = cl.get(nodeid, 'address').decode('ascii') + c = db.cursor + c.execute('update auth_user set email=%s where id=%s', (new, user)) + c.execute('update codereview_account set email=%s where id=%s', (new, user)) + # find issues where user is on nosy + c.execute('select nodeid,cc from issue_nosy, codereview_issue ' + 'where linkid=%s and nodeid=id', (user,)) + for issue, cc in c.fetchall(): + cc = cPickle.loads(base64.decodestring(cc)) + try: + cc[cc.index(old)] = new + except ValueError: + cc.append(new) + cc = base64.encodestring(cPickle.dumps(cc)) + c.execute('update codereview_issue set cc=%s where id=%s', (cc, user)) + def update_issue_cc(db, cl, nodeid, oldvalues): if 'nosy' not in oldvalues: Modified: tracker/instances/python-dev/scripts/update_email.py ============================================================================== --- tracker/instances/python-dev/scripts/update_email.py (original) +++ tracker/instances/python-dev/scripts/update_email.py Mon Apr 9 09:08:43 2012 @@ -1,5 +1,5 @@ #!/usr/bin/python -# cron job to update rietveld tables when the email address changes +# Update rietveld tables when the email address changes # this updates auth_user.email, codereview_account.email # and codereview_issue.cc, based on the nosy list s # it does not update codereview_issue.reviewers, since it would be @@ -7,6 +7,9 @@ # is something that has to be filled out separately in Rietveld. # It also does not update codereview_message, since these have already # been sent with the email addresses recorded in the database. +# +# This script is now part of rietveldreactor + import sys, os, base64, cPickle sys.path.insert(1,'/home/roundup/roundup/lib/python2.5/site-packages') import roundup.instance From python-checkins at python.org Mon Apr 9 09:20:46 2012 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 9 Apr 2012 09:20:46 +0200 (CEST) Subject: [Python-checkins] r88938 - tracker/instances/python-dev/detectors/rietveldreactor.py Message-ID: <3VR2wt51WbzMVW@mail.python.org> Author: martin.v.loewis Date: Mon Apr 9 09:20:46 2012 New Revision: 88938 Log: Make updates conditional on actual changes. Modified: tracker/instances/python-dev/detectors/rietveldreactor.py Modified: tracker/instances/python-dev/detectors/rietveldreactor.py ============================================================================== --- tracker/instances/python-dev/detectors/rietveldreactor.py (original) +++ tracker/instances/python-dev/detectors/rietveldreactor.py Mon Apr 9 09:20:46 2012 @@ -17,14 +17,15 @@ def update_django_user(db, cl, nodeid, oldvalues): user = nodeid - if 'username' in oldvalues: - newname = cl.get(nodeid, 'username') + oldname = oldvalues['username'] + newname = cl.get(nodeid, 'username') + if oldname != newname: c = db.cursor c.execute("update auth_user set username=%s where id=%s", (newname, user)) - if 'address' in oldvalues: - old = oldvalues['address'].decode('ascii') - new = cl.get(nodeid, 'address').decode('ascii') + old = oldvalues['address'].decode('ascii') + new = cl.get(nodeid, 'address').decode('ascii') + if old != new: c = db.cursor c.execute('update auth_user set email=%s where id=%s', (new, user)) c.execute('update codereview_account set email=%s where id=%s', (new, user)) From python-checkins at python.org Mon Apr 9 09:28:22 2012 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 9 Apr 2012 09:28:22 +0200 (CEST) Subject: [Python-checkins] r88939 - tracker/instances/python-dev/detectors/rietveldreactor.py Message-ID: <3VR35f3VP9zMX3@mail.python.org> Author: martin.v.loewis Date: Mon Apr 9 09:28:22 2012 New Revision: 88939 Log: Properly parametrize issue update. Modified: tracker/instances/python-dev/detectors/rietveldreactor.py Modified: tracker/instances/python-dev/detectors/rietveldreactor.py ============================================================================== --- tracker/instances/python-dev/detectors/rietveldreactor.py (original) +++ tracker/instances/python-dev/detectors/rietveldreactor.py Mon Apr 9 09:28:22 2012 @@ -39,7 +39,7 @@ except ValueError: cc.append(new) cc = base64.encodestring(cPickle.dumps(cc)) - c.execute('update codereview_issue set cc=%s where id=%s', (cc, user)) + c.execute('update codereview_issue set cc=%s where id=%s', (cc, issue)) def update_issue_cc(db, cl, nodeid, oldvalues): From python-checkins at python.org Mon Apr 9 13:04:21 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 09 Apr 2012 13:04:21 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Move_resolution_and?= =?utf8?q?_accuracy_definitions_to_the_Definition_section?= Message-ID: http://hg.python.org/peps/rev/4b1dbc2d1f08 changeset: 4208:4b1dbc2d1f08 user: Victor Stinner date: Mon Apr 09 13:04:15 2012 +0200 summary: PEP 418: Move resolution and accuracy definitions to the Definition section files: pep-0418.txt | 27 +++++++++++++++++---------- 1 files changed, 17 insertions(+), 10 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -214,6 +214,23 @@ Definitions =========== +Resolution +---------- + +The resolution is the smallest difference between two timestamps supported by +the format used by the clock. For example, clock_gettime() uses a timespec +structure which has two integer fields, tv_sec and tv_nsec, so the resolution +is 1 nanosecond. + +Accuracy +-------- + +The accuracy is the effective smallest difference of two timestamps of the +clock. It does not reflect the stability the clock rate. For example, +QueryPerformanceCounter() has a good accuracy but is known to not have a steady +rate. + + Monotonic --------- @@ -301,16 +318,6 @@ timeGetTime() 1 ms No ? ========================= =============== ================ ==================== -The resolution is the smallest difference between two timestamps -supported by the format used by the clock. For example, -clock_gettime() uses a timespec structure which has two integer -fields, tv_sec and tv_nsec, so the resolution is 1 nanosecond. - -The accuracy is the effective smallest difference of two timestamps of -the clock. It does not reflect the stability the clock rate. For -example, QueryPerformanceCounter() has a good accuracy but is known to -not have a steady rate. - Examples of clock accuracy on x86_64: ========================= ================ =============== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 9 13:21:39 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 09 Apr 2012 13:21:39 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Re-add_the_pseudo-c?= =?utf8?q?ode_for_time=2Eperf=5Fcounter=28=29?= Message-ID: http://hg.python.org/peps/rev/c7d0b8de3b40 changeset: 4209:c7d0b8de3b40 user: Victor Stinner date: Mon Apr 09 13:21:34 2012 +0200 summary: PEP 418: Re-add the pseudo-code for time.perf_counter() files: pep-0418.txt | 43 ++++++++++++++++++++++++++++++--------- 1 files changed, 33 insertions(+), 10 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -993,23 +993,46 @@ Deferred API: time.perf_counter() ================================= -Python does not provide a portable "performance counter" clock for benchmarking -or profiling. Each tool has to implement its own heuristic to decide which -clock is the best depending on the OS and on which counters are available. +Performance counter used for benchmarking and profiling. The reference point of +the returned value is undefined so only the difference of consecutive calls is +valid and is number of seconds. -A previous version of the PEP proposed a time.perf_counter() function using -QueryPerformanceCounter() on Windows, time.monotonic(), or falls back to the -system time. This function was not well defined and the idea is deferred. +Pseudo-code:: -Proposed names for such function: + def perf_counter(): + if perf_counter.use_performance_counter: + if perf_counter.cpu_frequency is None: + try: + perf_counter.cpu_frequency = float(_time.QueryPerformanceFrequency()) + except OSError: + # QueryPerformanceFrequency() fails if the installed + # hardware does not support a high-resolution performance + # counter + perf_counter.use_performance_counter = False + else: + return _time.QueryPerformanceCounter() / perf_counter.cpu_frequency + else: + return _time.QueryPerformanceCounter() / perf_counter.cpu_frequency + if perf_counter.use_monotonic: + # Monotonic clock is preferred over system clock + try: + return time.monotonic() + except OSError: + perf_counter.use_monotonic = False + return time.time() + perf_counter.use_performance_counter = (os.name == 'nt') + if perf_counter.use_performance_counter: + perf_counter.cpu_frequency = None + perf_counter.use_monotonic = hasattr(time, 'monotonic') + +Other names proposed for time.perf_counter(): * time.hires() * time.highres() - * time.perf_counter() * time.timer() -Python source code includes a portable library to get the process time: -`Tools/pybench/systimes.py +Python source code includes a portable library to get the process time (CPU +time): `Tools/pybench/systimes.py `_. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 9 15:13:12 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 09 Apr 2012 15:13:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_=2314533=3A_if_a_test_has_n?= =?utf8?q?o_test=5Fmain=2C_use_loadTestsFromModule=2E?= Message-ID: http://hg.python.org/cpython/rev/eff551437abd changeset: 76176:eff551437abd user: R David Murray date: Mon Apr 09 08:55:42 2012 -0400 summary: #14533: if a test has no test_main, use loadTestsFromModule. This moves us further in the direction of using normal unittest facilities instead of specialized regrtest ones. Any test module that can be correctly run currently using 'python unittest -m test.test_xxx' can now be converted to use normal unittest test loading by simply deleting its test_main, thus no longer requiring manual maintenance of the list of tests to run. (Not all tests can be converted that easily, since test_main sometimes does some additional things (such as reap_children or reap_threads). In those cases the extra code may be moved to setUpModule/tearDownModule methods, or perhaps the same ends can be achieved in a different way, such as moving the decorators to the test classes that need them, etc.) I don't advocate going through and making this change wholesale, but any time a list of tests in test_main would otherwise need to be updated, consideration should instead be given to deleting test_main. files: Doc/library/test.rst | 34 ++++++++++++++++--------------- Lib/test/regrtest.py | 15 +++++++------ Misc/NEWS | 6 +++++ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -80,17 +80,12 @@ ... more test classes ... - def test_main(): - support.run_unittest(MyTestCase1, - MyTestCase2, - ... list other tests ... - ) + if __name__ == '__main__': + unittest.main() - if __name__ == '__main__': - test_main() - -This boilerplate code allows the testing suite to be run by :mod:`test.regrtest` -as well as on its own as a script. +This code pattern allows the testing suite to be run by :mod:`test.regrtest`, +on its own as a script that supports the :mod:`unittest` CLI, or via the +`python -m unittest` CLI. The goal for regression testing is to try to break code. This leads to a few guidelines to be followed: @@ -129,22 +124,27 @@ as what type of input is used. Minimize code duplication by subclassing a basic test class with a class that specifies the input:: - class TestFuncAcceptsSequences(unittest.TestCase): + class TestFuncAcceptsSequencesMixin: func = mySuperWhammyFunction def test_func(self): self.func(self.arg) - class AcceptLists(TestFuncAcceptsSequences): + class AcceptLists(TestFuncAcceptsSequencesMixin, unittest.TestCase): arg = [1, 2, 3] - class AcceptStrings(TestFuncAcceptsSequences): + class AcceptStrings(TestFuncAcceptsSequencesMixin, unittest.TestCase): arg = 'abc' - class AcceptTuples(TestFuncAcceptsSequences): + class AcceptTuples(TestFuncAcceptsSequencesMixin, unittest.TestCase): arg = (1, 2, 3) + When using this pattern, remember that all classes that inherit from + `unittest.TestCase` are run as tests. The `Mixin` class in the example above + does not have any data and so can't be run by itself, thus it does not + inherit from `unittest.TestCase`. + .. seealso:: @@ -164,10 +164,12 @@ Running the script by itself automatically starts running all regression tests in the :mod:`test` package. It does this by finding all modules in the package whose name starts with ``test_``, importing them, and executing the -function :func:`test_main` if present. The names of tests to execute may also +function :func:`test_main` if present or loading the tests via +unittest.TestLoader.loadTestsFromModule if ``test_main`` does not exist. +The names of tests to execute may also be passed to the script. Specifying a single regression test (:program:`python -m test test_spam`) will minimize output and only print -whether the test passed or failed and thus minimize output. +whether the test passed or failed. Running :mod:`test` directly allows what resources are available for tests to use to be set. You do this by using the ``-u`` command-line diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -1228,14 +1228,15 @@ start_time = time.time() the_package = __import__(abstest, globals(), locals(), []) the_module = getattr(the_package, test) - # Old tests run to completion simply as a side-effect of - # being imported. For tests based on unittest or doctest, - # explicitly invoke their test_main() function (if it exists). - indirect_test = getattr(the_module, "test_main", None) - if indirect_test is not None: - indirect_test() + # If the test has a test_main, that will run the appropriate + # tests. If not, use normal unittest test loading. + test_runner = getattr(the_module, "test_main", None) + if test_runner is None: + tests = unittest.TestLoader().loadTestsFromModule(the_module) + test_runner = lambda: support.run_unittest(tests) + test_runner() if huntrleaks: - refleak = dash_R(the_module, test, indirect_test, + refleak = dash_R(the_module, test, test_runner, huntrleaks) test_time = time.time() - start_time except support.ResourceDenied as msg: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -51,6 +51,12 @@ - Issue #14493: Use gvfs-open or xdg-open in webbrowser. +Tests +----- + +- Issue #14355: Regrtest now supports the standard unittest test loading, and + will use it if a test file contains no `test_main` method. + What's New in Python 3.3.0 Alpha 2? =================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 15:13:13 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 09 Apr 2012 15:13:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Reflow_paragraph_=28not_tha?= =?utf8?q?t_it_helped_much=29=2E?= Message-ID: http://hg.python.org/cpython/rev/cdda6b129d79 changeset: 76177:cdda6b129d79 user: R David Murray date: Mon Apr 09 09:12:57 2012 -0400 summary: Reflow paragraph (not that it helped much). files: Doc/library/test.rst | 19 +++++++++---------- 1 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -160,16 +160,15 @@ The :mod:`test` package can be run as a script to drive Python's regression test suite, thanks to the :option:`-m` option: :program:`python -m test`. Under the hood, it uses :mod:`test.regrtest`; the call :program:`python -m -test.regrtest` used in previous Python versions still works). -Running the script by itself automatically starts running all regression -tests in the :mod:`test` package. It does this by finding all modules in the -package whose name starts with ``test_``, importing them, and executing the -function :func:`test_main` if present or loading the tests via -unittest.TestLoader.loadTestsFromModule if ``test_main`` does not exist. -The names of tests to execute may also -be passed to the script. Specifying a single regression test (:program:`python --m test test_spam`) will minimize output and only print -whether the test passed or failed. +test.regrtest` used in previous Python versions still works). Running the +script by itself automatically starts running all regression tests in the +:mod:`test` package. It does this by finding all modules in the package whose +name starts with ``test_``, importing them, and executing the function +:func:`test_main` if present or loading the tests via +unittest.TestLoader.loadTestsFromModule if ``test_main`` does not exist. The +names of tests to execute may also be passed to the script. Specifying a single +regression test (:program:`python -m test test_spam`) will minimize output and +only print whether the test passed or failed. Running :mod:`test` directly allows what resources are available for tests to use to be set. You do this by using the ``-u`` command-line -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 15:38:21 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 09 Apr 2012 15:38:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Rename_test=5F_file_that_is?= =?utf8?q?_really_a_support_file_to_remove_test=5F_prefix=2E?= Message-ID: http://hg.python.org/cpython/rev/46a620c87db8 changeset: 76178:46a620c87db8 user: R David Murray date: Mon Apr 09 09:37:52 2012 -0400 summary: Rename test_ file that is really a support file to remove test_ prefix. I thought I had run the full test suite before the last checkin, but obviously I didn't. test_multibytecodec_support.py isn't really a test file, it is a support file that contains a base test class. Rename it to multibytecodec_support so that regrtest test discovery doesn't think it is a test file that should be run. files: Lib/test/test_multibytecodec_support.py | 2 +- Lib/test/test_codecencodings_cn.py | 18 +++--- Lib/test/test_codecencodings_hk.py | 6 +- Lib/test/test_codecencodings_iso2022.py | 14 +++--- Lib/test/test_codecencodings_jp.py | 30 ++++++------ Lib/test/test_codecencodings_kr.py | 14 +++--- Lib/test/test_codecencodings_tw.py | 6 +- Lib/test/test_codecmaps_cn.py | 8 +- Lib/test/test_codecmaps_hk.py | 4 +- Lib/test/test_codecmaps_jp.py | 12 ++-- Lib/test/test_codecmaps_kr.py | 8 +- Lib/test/test_codecmaps_tw.py | 6 +- 12 files changed, 64 insertions(+), 64 deletions(-) diff --git a/Lib/test/test_multibytecodec_support.py b/Lib/test/multibytecodec_support.py rename from Lib/test/test_multibytecodec_support.py rename to Lib/test/multibytecodec_support.py --- a/Lib/test/test_multibytecodec_support.py +++ b/Lib/test/multibytecodec_support.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# test_multibytecodec_support.py +# multibytecodec_support.py # Common Unittest Routines for CJK codecs # diff --git a/Lib/test/test_codecencodings_cn.py b/Lib/test/test_codecencodings_cn.py --- a/Lib/test/test_codecencodings_cn.py +++ b/Lib/test/test_codecencodings_cn.py @@ -5,12 +5,12 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class Test_GB2312(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_GB2312(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'gb2312' - tstring = test_multibytecodec_support.load_teststring('gb2312') + tstring = multibytecodec_support.load_teststring('gb2312') codectests = ( # invalid bytes (b"abc\x81\x81\xc1\xc4", "strict", None), @@ -21,9 +21,9 @@ (b"\xc1\x64", "strict", None), ) -class Test_GBK(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_GBK(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'gbk' - tstring = test_multibytecodec_support.load_teststring('gbk') + tstring = multibytecodec_support.load_teststring('gbk') codectests = ( # invalid bytes (b"abc\x80\x80\xc1\xc4", "strict", None), @@ -35,9 +35,9 @@ ("\u30fb", "strict", None), ) -class Test_GB18030(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_GB18030(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'gb18030' - tstring = test_multibytecodec_support.load_teststring('gb18030') + tstring = multibytecodec_support.load_teststring('gb18030') codectests = ( # invalid bytes (b"abc\x80\x80\xc1\xc4", "strict", None), @@ -53,9 +53,9 @@ ) has_iso10646 = True -class Test_HZ(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_HZ(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'hz' - tstring = test_multibytecodec_support.load_teststring('hz') + tstring = multibytecodec_support.load_teststring('hz') codectests = ( # test '~\n' (3 lines) (b'This sentence is in ASCII.\n' diff --git a/Lib/test/test_codecencodings_hk.py b/Lib/test/test_codecencodings_hk.py --- a/Lib/test/test_codecencodings_hk.py +++ b/Lib/test/test_codecencodings_hk.py @@ -5,12 +5,12 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class Test_Big5HKSCS(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_Big5HKSCS(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'big5hkscs' - tstring = test_multibytecodec_support.load_teststring('big5hkscs') + tstring = multibytecodec_support.load_teststring('big5hkscs') codectests = ( # invalid bytes (b"abc\x80\x80\xc1\xc4", "strict", None), diff --git a/Lib/test/test_codecencodings_iso2022.py b/Lib/test/test_codecencodings_iso2022.py --- a/Lib/test/test_codecencodings_iso2022.py +++ b/Lib/test/test_codecencodings_iso2022.py @@ -3,7 +3,7 @@ # Codec encoding tests for ISO 2022 encodings. from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest COMMON_CODEC_TESTS = ( @@ -13,23 +13,23 @@ (b'ab\x1B$def', 'replace', 'ab\uFFFD'), ) -class Test_ISO2022_JP(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_ISO2022_JP(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'iso2022_jp' - tstring = test_multibytecodec_support.load_teststring('iso2022_jp') + tstring = multibytecodec_support.load_teststring('iso2022_jp') codectests = COMMON_CODEC_TESTS + ( (b'ab\x1BNdef', 'replace', 'ab\x1BNdef'), ) -class Test_ISO2022_JP2(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_ISO2022_JP2(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'iso2022_jp_2' - tstring = test_multibytecodec_support.load_teststring('iso2022_jp') + tstring = multibytecodec_support.load_teststring('iso2022_jp') codectests = COMMON_CODEC_TESTS + ( (b'ab\x1BNdef', 'replace', 'abdef'), ) -class Test_ISO2022_KR(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_ISO2022_KR(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'iso2022_kr' - tstring = test_multibytecodec_support.load_teststring('iso2022_kr') + tstring = multibytecodec_support.load_teststring('iso2022_kr') codectests = COMMON_CODEC_TESTS + ( (b'ab\x1BNdef', 'replace', 'ab\x1BNdef'), ) diff --git a/Lib/test/test_codecencodings_jp.py b/Lib/test/test_codecencodings_jp.py --- a/Lib/test/test_codecencodings_jp.py +++ b/Lib/test/test_codecencodings_jp.py @@ -5,12 +5,12 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class Test_CP932(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_CP932(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'cp932' - tstring = test_multibytecodec_support.load_teststring('shift_jis') + tstring = multibytecodec_support.load_teststring('shift_jis') codectests = ( # invalid bytes (b"abc\x81\x00\x81\x00\x82\x84", "strict", None), @@ -41,30 +41,30 @@ (b"\x8eXY", "replace", "\ufffdXY"), ) -class Test_EUC_JIS_2004(test_multibytecodec_support.TestBase, +class Test_EUC_JIS_2004(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'euc_jis_2004' - tstring = test_multibytecodec_support.load_teststring('euc_jisx0213') + tstring = multibytecodec_support.load_teststring('euc_jisx0213') codectests = euc_commontests xmlcharnametest = ( "\xab\u211c\xbb = \u2329\u1234\u232a", b"\xa9\xa8ℜ\xa9\xb2 = ⟨ሴ⟩" ) -class Test_EUC_JISX0213(test_multibytecodec_support.TestBase, +class Test_EUC_JISX0213(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'euc_jisx0213' - tstring = test_multibytecodec_support.load_teststring('euc_jisx0213') + tstring = multibytecodec_support.load_teststring('euc_jisx0213') codectests = euc_commontests xmlcharnametest = ( "\xab\u211c\xbb = \u2329\u1234\u232a", b"\xa9\xa8ℜ\xa9\xb2 = ⟨ሴ⟩" ) -class Test_EUC_JP_COMPAT(test_multibytecodec_support.TestBase, +class Test_EUC_JP_COMPAT(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'euc_jp' - tstring = test_multibytecodec_support.load_teststring('euc_jp') + tstring = multibytecodec_support.load_teststring('euc_jp') codectests = euc_commontests + ( ("\xa5", "strict", b"\x5c"), ("\u203e", "strict", b"\x7e"), @@ -76,9 +76,9 @@ (b"abc\x80\x80\x82\x84def", "ignore", "abc\uff44def"), ) -class Test_SJIS_COMPAT(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_SJIS_COMPAT(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'shift_jis' - tstring = test_multibytecodec_support.load_teststring('shift_jis') + tstring = multibytecodec_support.load_teststring('shift_jis') codectests = shiftjis_commonenctests + ( (b"abc\x80\x80\x82\x84", "replace", "abc\ufffd\ufffd\uff44"), (b"abc\x80\x80\x82\x84\x88", "replace", "abc\ufffd\ufffd\uff44\ufffd"), @@ -90,9 +90,9 @@ (b"abc\xFF\x58", "replace", "abc\ufffdX"), ) -class Test_SJIS_2004(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_SJIS_2004(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'shift_jis_2004' - tstring = test_multibytecodec_support.load_teststring('shift_jis') + tstring = multibytecodec_support.load_teststring('shift_jis') codectests = shiftjis_commonenctests + ( (b"\\\x7e", "strict", "\xa5\u203e"), (b"\x81\x5f\x81\x61\x81\x7c", "strict", "\\\u2016\u2212"), @@ -108,9 +108,9 @@ b"\x85Gℜ\x85Q = ⟨ሴ⟩" ) -class Test_SJISX0213(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_SJISX0213(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'shift_jisx0213' - tstring = test_multibytecodec_support.load_teststring('shift_jisx0213') + tstring = multibytecodec_support.load_teststring('shift_jisx0213') codectests = shiftjis_commonenctests + ( (b"abc\x80\x80\x82\x84", "replace", "abc\ufffd\ufffd\uff44"), (b"abc\x80\x80\x82\x84\x88", "replace", "abc\ufffd\ufffd\uff44\ufffd"), diff --git a/Lib/test/test_codecencodings_kr.py b/Lib/test/test_codecencodings_kr.py --- a/Lib/test/test_codecencodings_kr.py +++ b/Lib/test/test_codecencodings_kr.py @@ -5,12 +5,12 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class Test_CP949(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_CP949(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'cp949' - tstring = test_multibytecodec_support.load_teststring('cp949') + tstring = multibytecodec_support.load_teststring('cp949') codectests = ( # invalid bytes (b"abc\x80\x80\xc1\xc4", "strict", None), @@ -20,9 +20,9 @@ (b"abc\x80\x80\xc1\xc4", "ignore", "abc\uc894"), ) -class Test_EUCKR(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_EUCKR(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'euc_kr' - tstring = test_multibytecodec_support.load_teststring('euc_kr') + tstring = multibytecodec_support.load_teststring('euc_kr') codectests = ( # invalid bytes (b"abc\x80\x80\xc1\xc4", "strict", None), @@ -51,9 +51,9 @@ (b"\xc1\xc4", "strict", "\uc894"), ) -class Test_JOHAB(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_JOHAB(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'johab' - tstring = test_multibytecodec_support.load_teststring('johab') + tstring = multibytecodec_support.load_teststring('johab') codectests = ( # invalid bytes (b"abc\x80\x80\xc1\xc4", "strict", None), diff --git a/Lib/test/test_codecencodings_tw.py b/Lib/test/test_codecencodings_tw.py --- a/Lib/test/test_codecencodings_tw.py +++ b/Lib/test/test_codecencodings_tw.py @@ -5,12 +5,12 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class Test_Big5(test_multibytecodec_support.TestBase, unittest.TestCase): +class Test_Big5(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'big5' - tstring = test_multibytecodec_support.load_teststring('big5') + tstring = multibytecodec_support.load_teststring('big5') codectests = ( # invalid bytes (b"abc\x80\x80\xc1\xc4", "strict", None), diff --git a/Lib/test/test_codecmaps_cn.py b/Lib/test/test_codecmaps_cn.py --- a/Lib/test/test_codecmaps_cn.py +++ b/Lib/test/test_codecmaps_cn.py @@ -5,21 +5,21 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class TestGB2312Map(test_multibytecodec_support.TestBase_Mapping, +class TestGB2312Map(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'gb2312' mapfileurl = 'http://people.freebsd.org/~perky/i18n/EUC-CN.TXT' -class TestGBKMap(test_multibytecodec_support.TestBase_Mapping, +class TestGBKMap(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'gbk' mapfileurl = 'http://www.unicode.org/Public/MAPPINGS/VENDORS/' \ 'MICSFT/WINDOWS/CP936.TXT' -class TestGB18030Map(test_multibytecodec_support.TestBase_Mapping, +class TestGB18030Map(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'gb18030' mapfileurl = 'http://source.icu-project.org/repos/icu/data/' \ diff --git a/Lib/test/test_codecmaps_hk.py b/Lib/test/test_codecmaps_hk.py --- a/Lib/test/test_codecmaps_hk.py +++ b/Lib/test/test_codecmaps_hk.py @@ -5,10 +5,10 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class TestBig5HKSCSMap(test_multibytecodec_support.TestBase_Mapping, +class TestBig5HKSCSMap(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'big5hkscs' mapfileurl = 'http://people.freebsd.org/~perky/i18n/BIG5HKSCS-2004.TXT' diff --git a/Lib/test/test_codecmaps_jp.py b/Lib/test/test_codecmaps_jp.py --- a/Lib/test/test_codecmaps_jp.py +++ b/Lib/test/test_codecmaps_jp.py @@ -5,10 +5,10 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class TestCP932Map(test_multibytecodec_support.TestBase_Mapping, +class TestCP932Map(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'cp932' mapfileurl = 'http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/' \ @@ -24,14 +24,14 @@ supmaps.append((bytes([i]), chr(i+0xfec0))) -class TestEUCJPCOMPATMap(test_multibytecodec_support.TestBase_Mapping, +class TestEUCJPCOMPATMap(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'euc_jp' mapfilename = 'EUC-JP.TXT' mapfileurl = 'http://people.freebsd.org/~perky/i18n/EUC-JP.TXT' -class TestSJISCOMPATMap(test_multibytecodec_support.TestBase_Mapping, +class TestSJISCOMPATMap(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'shift_jis' mapfilename = 'SHIFTJIS.TXT' @@ -46,14 +46,14 @@ (b'\x81_', '\\'), ] -class TestEUCJISX0213Map(test_multibytecodec_support.TestBase_Mapping, +class TestEUCJISX0213Map(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'euc_jisx0213' mapfilename = 'EUC-JISX0213.TXT' mapfileurl = 'http://people.freebsd.org/~perky/i18n/EUC-JISX0213.TXT' -class TestSJISX0213Map(test_multibytecodec_support.TestBase_Mapping, +class TestSJISX0213Map(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'shift_jisx0213' mapfilename = 'SHIFT_JISX0213.TXT' diff --git a/Lib/test/test_codecmaps_kr.py b/Lib/test/test_codecmaps_kr.py --- a/Lib/test/test_codecmaps_kr.py +++ b/Lib/test/test_codecmaps_kr.py @@ -5,17 +5,17 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class TestCP949Map(test_multibytecodec_support.TestBase_Mapping, +class TestCP949Map(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'cp949' mapfileurl = 'http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT' \ '/WINDOWS/CP949.TXT' -class TestEUCKRMap(test_multibytecodec_support.TestBase_Mapping, +class TestEUCKRMap(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'euc_kr' mapfileurl = 'http://people.freebsd.org/~perky/i18n/EUC-KR.TXT' @@ -25,7 +25,7 @@ pass_dectest = [(b'\xa4\xd4', '\u3164')] -class TestJOHABMap(test_multibytecodec_support.TestBase_Mapping, +class TestJOHABMap(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'johab' mapfileurl = 'http://www.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/' \ diff --git a/Lib/test/test_codecmaps_tw.py b/Lib/test/test_codecmaps_tw.py --- a/Lib/test/test_codecmaps_tw.py +++ b/Lib/test/test_codecmaps_tw.py @@ -5,16 +5,16 @@ # from test import support -from test import test_multibytecodec_support +from test import multibytecodec_support import unittest -class TestBIG5Map(test_multibytecodec_support.TestBase_Mapping, +class TestBIG5Map(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'big5' mapfileurl = 'http://www.unicode.org/Public/MAPPINGS/OBSOLETE/' \ 'EASTASIA/OTHER/BIG5.TXT' -class TestCP950Map(test_multibytecodec_support.TestBase_Mapping, +class TestCP950Map(multibytecodec_support.TestBase_Mapping, unittest.TestCase): encoding = 'cp950' mapfileurl = 'http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/' \ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 16:42:21 2012 From: python-checkins at python.org (barry.warsaw) Date: Mon, 09 Apr 2012 16:42:21 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_274_has_been_updated_to_re?= =?utf8?q?flect_current_reality=2E?= Message-ID: http://hg.python.org/peps/rev/fc28ffc78aca changeset: 4210:fc28ffc78aca user: Barry Warsaw date: Mon Apr 09 10:42:15 2012 -0400 summary: PEP 274 has been updated to reflect current reality. files: pep-0274.txt | 62 +++++++++++++-------------------------- 1 files changed, 21 insertions(+), 41 deletions(-) diff --git a/pep-0274.txt b/pep-0274.txt --- a/pep-0274.txt +++ b/pep-0274.txt @@ -2,11 +2,11 @@ Title: Dict Comprehensions Version: $Revision$ Last-Modified: $Date$ -Author: barry at python.org (Barry Warsaw) -Status: Withdrawn +Author: Barry Warsaw +Status: Accepted Type: Standards Track Created: 25-Oct-2001 -Python-Version: 2.3 +Python-Version: 2.7, 3.0 (originally 2.3) Post-History: 29-Oct-2001 @@ -19,13 +19,20 @@ very similar to list comprehensions, except that they produce Python dictionary objects instead of list objects. + Resolution - This PEP is withdrawn. Substantially all of its benefits were - subsumed by generator expressions coupled with the dict() constructor. + This PEP was originally written for inclusion in Python 2.3. It + was withdrawn after observation that substantially all of its + benefits were subsumed by generator expressions coupled with the + dict() constructor. - However, Python 3.0 introduces this exact feature, as well as the - closely related set comprehensions. + However, Python 2.7 and 3.0 introduces this exact feature, as well + as the closely related set comprehensions. On 2012-04-09, the PEP + was changed to reflect this reality by updating its Status to + Accepted, and updating the Python-Version field. The Open + Questions section was also removed since these have been long + resolved by the current implementation. Proposed Solution @@ -33,10 +40,9 @@ Dict comprehensions are just like list comprehensions, except that you group the expression using curly braces instead of square braces. Also, the left part before the `for' keyword expresses - both a key and a value, separated by a colon. (There is an - optional part of this PEP that allows you to use a shortcut to - express just the value.) The notation is specifically designed to - remind you of list comprehensions as applied to dictionaries. + both a key and a value, separated by a colon. The notation is + specifically designed to remind you of list comprehensions as + applied to dictionaries. Rationale @@ -65,7 +71,7 @@ The semantics of dict comprehensions can actually be demonstrated in stock Python 2.2, by passing a list comprehension to the - builtin dictionary constructor: + built-in dictionary constructor: >>> dict([(i, chr(65+i)) for i in range(4)]) @@ -73,7 +79,7 @@ >>> {i : chr(65+i) for i in range(4)} - The dictionary constructor approach has two dictinct disadvantages + The dictionary constructor approach has two distinct disadvantages from the proposed syntax though. First, it isn't as legible as a dict comprehension. Second, it forces the programmer to create an in-core list object first, which could be expensive. @@ -104,36 +110,10 @@ 2, 3): 5} -Open Issues - - - There is one further shortcut we could adopt. Suppose we wanted - to create a set of items, such as in the "list_of_email_addrs" - example above. Here, we're simply taking the target of the for - loop and turning that into the key for the dict comprehension. - The assertion is that this would be a common idiom, so the - shortcut below allows for an easy spelling of it, by allow us to - omit the "key :" part of the left hand clause: - - >>> print {1 for x in list_of_email_addrs} - {'barry at zope.com' : 1, 'barry at python.org' : 1, 'guido at python.org' : 1} - - Or say we wanted to map email addresses to the MX record handling - their mail: - - >>> print {mx_for_addr(x) for x in list_of_email_addrs} - {'barry at zope.com' : 'mail.zope.com', - 'barry at python.org' : 'mail.python.org, - 'guido at python.org' : 'mail.python.org, - } - - Questions: what about nested loops? Where does the key come - from? The shortcut probably doesn't save much typing, and comes - at the expense of legibility, so it's of dubious value. - - Implementation - TBD + All implementation details were resolved in the Python 2.7 and 3.0 + time-frame. References -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 9 17:09:46 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 17:09:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313165=3A_stringben?= =?utf8?q?ch_is_now_available_in_the_Tools/stringbench_folder=2E?= Message-ID: http://hg.python.org/cpython/rev/704630a9c5d5 changeset: 76179:704630a9c5d5 user: Antoine Pitrou date: Mon Apr 09 17:03:32 2012 +0200 summary: Issue #13165: stringbench is now available in the Tools/stringbench folder. It used to live in its own SVN project. files: Misc/NEWS | 6 + Tools/README | 3 + Tools/stringbench/README | 68 + Tools/stringbench/stringbench.py | 1483 ++++++++++++++++++ 4 files changed, 1560 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,12 @@ - Issue #14355: Regrtest now supports the standard unittest test loading, and will use it if a test file contains no `test_main` method. +Tools / Demos +------------- + +- Issue #13165: stringbench is now available in the Tools/stringbench folder. + It used to live in its own SVN project. + What's New in Python 3.3.0 Alpha 2? =================================== diff --git a/Tools/README b/Tools/README --- a/Tools/README +++ b/Tools/README @@ -32,6 +32,9 @@ tabs and spaces, and 2to3, which converts Python 2 code to Python 3 code. +stringbench A suite of micro-benchmarks for various operations on + strings (both 8-bit and unicode). + test2to3 A demonstration of how to use 2to3 transparently in setup.py. unicode Tools for generating unicodedata and codecs from unicode.org diff --git a/Tools/stringbench/README b/Tools/stringbench/README new file mode 100644 --- /dev/null +++ b/Tools/stringbench/README @@ -0,0 +1,68 @@ +stringbench is a set of performance tests comparing byte string +operations with unicode operations. The two string implementations +are loosely based on each other and sometimes the algorithm for one is +faster than the other. + +These test set was started at the Need For Speed sprint in Reykjavik +to identify which string methods could be sped up quickly and to +identify obvious places for improvement. + +Here is an example of a benchmark + + + at bench('"Andrew".startswith("A")', 'startswith single character', 1000) +def startswith_single(STR): + s1 = STR("Andrew") + s2 = STR("A") + s1_startswith = s1.startswith + for x in _RANGE_1000: + s1_startswith(s2) + +The bench decorator takes three parameters. The first is a short +description of how the code works. In most cases this is Python code +snippet. It is not the code which is actually run because the real +code is hand-optimized to focus on the method being tested. + +The second parameter is a group title. All benchmarks with the same +group title are listed together. This lets you compare different +implementations of the same algorithm, such as "t in s" +vs. "s.find(t)". + +The last is a count. Each benchmark loops over the algorithm either +100 or 1000 times, depending on the algorithm performance. The output +time is the time per benchmark call so the reader needs a way to know +how to scale the performance. + +These parameters become function attributes. + + +Here is an example of the output + + +========== count newlines +38.54 41.60 92.7 ...text.with.2000.newlines.count("\n") (*100) +========== early match, single character +1.14 1.18 96.8 ("A"*1000).find("A") (*1000) +0.44 0.41 105.6 "A" in "A"*1000 (*1000) +1.15 1.17 98.1 ("A"*1000).index("A") (*1000) + +The first column is the run time in milliseconds for byte strings. +The second is the run time for unicode strings. The third is a +percentage; byte time / unicode time. It's the percentage by which +unicode is faster than byte strings. + +The last column contains the code snippet and the repeat count for the +internal benchmark loop. + +The times are computed with 'timeit.py' which repeats the test more +and more times until the total time takes over 0.2 seconds, returning +the best time for a single iteration. + +The final line of the output is the cumulative time for byte and +unicode strings, and the overall performance of unicode relative to +bytes. For example + +4079.83 5432.25 75.1 TOTAL + +However, this has no meaning as it evenly weights every test. + diff --git a/Tools/stringbench/stringbench.py b/Tools/stringbench/stringbench.py new file mode 100755 --- /dev/null +++ b/Tools/stringbench/stringbench.py @@ -0,0 +1,1483 @@ + +# Various microbenchmarks comparing unicode and byte string performance +# Please keep this file both 2.x and 3.x compatible! + +import timeit +import itertools +import operator +import re +import sys +import datetime +import optparse + +VERSION = '2.0' + +def p(*args): + sys.stdout.write(' '.join(str(s) for s in args) + '\n') + +if sys.version_info >= (3,): + BYTES = bytes_from_str = lambda x: x.encode('ascii') + UNICODE = unicode_from_str = lambda x: x +else: + BYTES = bytes_from_str = lambda x: x + UNICODE = unicode_from_str = lambda x: x.decode('ascii') + +class UnsupportedType(TypeError): + pass + + +p('stringbench v%s' % VERSION) +p(sys.version) +p(datetime.datetime.now()) + +REPEAT = 1 +REPEAT = 3 +#REPEAT = 7 + +if __name__ != "__main__": + raise SystemExit("Must run as main program") + +parser = optparse.OptionParser() +parser.add_option("-R", "--skip-re", dest="skip_re", + action="store_true", + help="skip regular expression tests") +parser.add_option("-8", "--8-bit", dest="bytes_only", + action="store_true", + help="only do 8-bit string benchmarks") +parser.add_option("-u", "--unicode", dest="unicode_only", + action="store_true", + help="only do Unicode string benchmarks") + + +_RANGE_1000 = list(range(1000)) +_RANGE_100 = list(range(100)) +_RANGE_10 = list(range(10)) + +dups = {} +def bench(s, group, repeat_count): + def blah(f): + if f.__name__ in dups: + raise AssertionError("Multiple functions with same name: %r" % + (f.__name__,)) + dups[f.__name__] = 1 + f.comment = s + f.is_bench = True + f.group = group + f.repeat_count = repeat_count + return f + return blah + +def uses_re(f): + f.uses_re = True + +####### 'in' comparisons + + at bench('"A" in "A"*1000', "early match, single character", 1000) +def in_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + for x in _RANGE_1000: + s2 in s1 + + at bench('"B" in "A"*1000', "no match, single character", 1000) +def in_test_no_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("B") + for x in _RANGE_1000: + s2 in s1 + + + at bench('"AB" in "AB"*1000', "early match, two characters", 1000) +def in_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + for x in _RANGE_1000: + s2 in s1 + + at bench('"BC" in "AB"*1000', "no match, two characters", 1000) +def in_test_no_match_two_character(STR): + s1 = STR("AB" * 1000) + s2 = STR("BC") + for x in _RANGE_1000: + s2 in s1 + + at bench('"BC" in ("AB"*300+"C")', "late match, two characters", 1000) +def in_test_slow_match_two_characters(STR): + s1 = STR("AB" * 300+"C") + s2 = STR("BC") + for x in _RANGE_1000: + s2 in s1 + + at bench('s="ABC"*33; (s+"E") in ((s+"D")*300+s+"E")', + "late match, 100 characters", 100) +def in_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = (m+d)*300 + m+e + s2 = m+e + for x in _RANGE_100: + s2 in s1 + +# Try with regex + at uses_re + at bench('s="ABC"*33; re.compile(s+"D").search((s+"D")*300+s+"E")', + "late match, 100 characters", 100) +def re_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = (m+d)*300 + m+e + s2 = m+e + pat = re.compile(s2) + search = pat.search + for x in _RANGE_100: + search(s1) + + +#### same tests as 'in' but use 'find' + + at bench('("A"*1000).find("A")', "early match, single character", 1000) +def find_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + s1_find = s1.find + for x in _RANGE_1000: + s1_find(s2) + + at bench('("A"*1000).find("B")', "no match, single character", 1000) +def find_test_no_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("B") + s1_find = s1.find + for x in _RANGE_1000: + s1_find(s2) + + + at bench('("AB"*1000).find("AB")', "early match, two characters", 1000) +def find_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + s1_find = s1.find + for x in _RANGE_1000: + s1_find(s2) + + at bench('("AB"*1000).find("BC")', "no match, two characters", 1000) +def find_test_no_match_two_character(STR): + s1 = STR("AB" * 1000) + s2 = STR("BC") + s1_find = s1.find + for x in _RANGE_1000: + s1_find(s2) + + at bench('("AB"*1000).find("CA")', "no match, two characters", 1000) +def find_test_no_match_two_character_bis(STR): + s1 = STR("AB" * 1000) + s2 = STR("CA") + s1_find = s1.find + for x in _RANGE_1000: + s1_find(s2) + + at bench('("AB"*300+"C").find("BC")', "late match, two characters", 1000) +def find_test_slow_match_two_characters(STR): + s1 = STR("AB" * 300+"C") + s2 = STR("BC") + s1_find = s1.find + for x in _RANGE_1000: + s1_find(s2) + + at bench('("AB"*300+"CA").find("CA")', "late match, two characters", 1000) +def find_test_slow_match_two_characters_bis(STR): + s1 = STR("AB" * 300+"CA") + s2 = STR("CA") + s1_find = s1.find + for x in _RANGE_1000: + s1_find(s2) + + at bench('s="ABC"*33; ((s+"D")*500+s+"E").find(s+"E")', + "late match, 100 characters", 100) +def find_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = (m+d)*500 + m+e + s2 = m+e + s1_find = s1.find + for x in _RANGE_100: + s1_find(s2) + + at bench('s="ABC"*33; ((s+"D")*500+"E"+s).find("E"+s)', + "late match, 100 characters", 100) +def find_test_slow_match_100_characters_bis(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = (m+d)*500 + e+m + s2 = e+m + s1_find = s1.find + for x in _RANGE_100: + s1_find(s2) + + +#### Same tests for 'rfind' + + at bench('("A"*1000).rfind("A")', "early match, single character", 1000) +def rfind_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + s1_rfind = s1.rfind + for x in _RANGE_1000: + s1_rfind(s2) + + at bench('("A"*1000).rfind("B")', "no match, single character", 1000) +def rfind_test_no_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("B") + s1_rfind = s1.rfind + for x in _RANGE_1000: + s1_rfind(s2) + + + at bench('("AB"*1000).rfind("AB")', "early match, two characters", 1000) +def rfind_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + s1_rfind = s1.rfind + for x in _RANGE_1000: + s1_rfind(s2) + + at bench('("AB"*1000).rfind("BC")', "no match, two characters", 1000) +def rfind_test_no_match_two_character(STR): + s1 = STR("AB" * 1000) + s2 = STR("BC") + s1_rfind = s1.rfind + for x in _RANGE_1000: + s1_rfind(s2) + + at bench('("AB"*1000).rfind("CA")', "no match, two characters", 1000) +def rfind_test_no_match_two_character_bis(STR): + s1 = STR("AB" * 1000) + s2 = STR("CA") + s1_rfind = s1.rfind + for x in _RANGE_1000: + s1_rfind(s2) + + at bench('("C"+"AB"*300).rfind("CA")', "late match, two characters", 1000) +def rfind_test_slow_match_two_characters(STR): + s1 = STR("C" + "AB" * 300) + s2 = STR("CA") + s1_rfind = s1.rfind + for x in _RANGE_1000: + s1_rfind(s2) + + at bench('("BC"+"AB"*300).rfind("BC")', "late match, two characters", 1000) +def rfind_test_slow_match_two_characters_bis(STR): + s1 = STR("BC" + "AB" * 300) + s2 = STR("BC") + s1_rfind = s1.rfind + for x in _RANGE_1000: + s1_rfind(s2) + + at bench('s="ABC"*33; ("E"+s+("D"+s)*500).rfind("E"+s)', + "late match, 100 characters", 100) +def rfind_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = e+m + (d+m)*500 + s2 = e+m + s1_rfind = s1.rfind + for x in _RANGE_100: + s1_rfind(s2) + + at bench('s="ABC"*33; (s+"E"+("D"+s)*500).rfind(s+"E")', + "late match, 100 characters", 100) +def rfind_test_slow_match_100_characters_bis(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = m+e + (d+m)*500 + s2 = m+e + s1_rfind = s1.rfind + for x in _RANGE_100: + s1_rfind(s2) + + +#### Now with index. +# Skip the ones which fail because that would include exception overhead. + + at bench('("A"*1000).index("A")', "early match, single character", 1000) +def index_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + s1_index = s1.index + for x in _RANGE_1000: + s1_index(s2) + + at bench('("AB"*1000).index("AB")', "early match, two characters", 1000) +def index_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + s1_index = s1.index + for x in _RANGE_1000: + s1_index(s2) + + at bench('("AB"*300+"C").index("BC")', "late match, two characters", 1000) +def index_test_slow_match_two_characters(STR): + s1 = STR("AB" * 300+"C") + s2 = STR("BC") + s1_index = s1.index + for x in _RANGE_1000: + s1_index(s2) + + at bench('s="ABC"*33; ((s+"D")*500+s+"E").index(s+"E")', + "late match, 100 characters", 100) +def index_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = (m+d)*500 + m+e + s2 = m+e + s1_index = s1.index + for x in _RANGE_100: + s1_index(s2) + + +#### Same for rindex + + at bench('("A"*1000).rindex("A")', "early match, single character", 1000) +def rindex_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + s1_rindex = s1.rindex + for x in _RANGE_1000: + s1_rindex(s2) + + at bench('("AB"*1000).rindex("AB")', "early match, two characters", 1000) +def rindex_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + s1_rindex = s1.rindex + for x in _RANGE_1000: + s1_rindex(s2) + + at bench('("C"+"AB"*300).rindex("CA")', "late match, two characters", 1000) +def rindex_test_slow_match_two_characters(STR): + s1 = STR("C" + "AB" * 300) + s2 = STR("CA") + s1_rindex = s1.rindex + for x in _RANGE_1000: + s1_rindex(s2) + + at bench('s="ABC"*33; ("E"+s+("D"+s)*500).rindex("E"+s)', + "late match, 100 characters", 100) +def rindex_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = e + m + (d+m)*500 + s2 = e + m + s1_rindex = s1.rindex + for x in _RANGE_100: + s1_rindex(s2) + + +#### Same for partition + + at bench('("A"*1000).partition("A")', "early match, single character", 1000) +def partition_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + s1_partition = s1.partition + for x in _RANGE_1000: + s1_partition(s2) + + at bench('("A"*1000).partition("B")', "no match, single character", 1000) +def partition_test_no_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("B") + s1_partition = s1.partition + for x in _RANGE_1000: + s1_partition(s2) + + + at bench('("AB"*1000).partition("AB")', "early match, two characters", 1000) +def partition_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + s1_partition = s1.partition + for x in _RANGE_1000: + s1_partition(s2) + + at bench('("AB"*1000).partition("BC")', "no match, two characters", 1000) +def partition_test_no_match_two_character(STR): + s1 = STR("AB" * 1000) + s2 = STR("BC") + s1_partition = s1.partition + for x in _RANGE_1000: + s1_partition(s2) + + at bench('("AB"*300+"C").partition("BC")', "late match, two characters", 1000) +def partition_test_slow_match_two_characters(STR): + s1 = STR("AB" * 300+"C") + s2 = STR("BC") + s1_partition = s1.partition + for x in _RANGE_1000: + s1_partition(s2) + + at bench('s="ABC"*33; ((s+"D")*500+s+"E").partition(s+"E")', + "late match, 100 characters", 100) +def partition_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = (m+d)*500 + m+e + s2 = m+e + s1_partition = s1.partition + for x in _RANGE_100: + s1_partition(s2) + + +#### Same for rpartition + + at bench('("A"*1000).rpartition("A")', "early match, single character", 1000) +def rpartition_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + s1_rpartition = s1.rpartition + for x in _RANGE_1000: + s1_rpartition(s2) + + at bench('("A"*1000).rpartition("B")', "no match, single character", 1000) +def rpartition_test_no_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("B") + s1_rpartition = s1.rpartition + for x in _RANGE_1000: + s1_rpartition(s2) + + + at bench('("AB"*1000).rpartition("AB")', "early match, two characters", 1000) +def rpartition_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + s1_rpartition = s1.rpartition + for x in _RANGE_1000: + s1_rpartition(s2) + + at bench('("AB"*1000).rpartition("BC")', "no match, two characters", 1000) +def rpartition_test_no_match_two_character(STR): + s1 = STR("AB" * 1000) + s2 = STR("BC") + s1_rpartition = s1.rpartition + for x in _RANGE_1000: + s1_rpartition(s2) + + at bench('("C"+"AB"*300).rpartition("CA")', "late match, two characters", 1000) +def rpartition_test_slow_match_two_characters(STR): + s1 = STR("C" + "AB" * 300) + s2 = STR("CA") + s1_rpartition = s1.rpartition + for x in _RANGE_1000: + s1_rpartition(s2) + + at bench('s="ABC"*33; ("E"+s+("D"+s)*500).rpartition("E"+s)', + "late match, 100 characters", 100) +def rpartition_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = e + m + (d+m)*500 + s2 = e + m + s1_rpartition = s1.rpartition + for x in _RANGE_100: + s1_rpartition(s2) + + +#### Same for split(s, 1) + + at bench('("A"*1000).split("A", 1)', "early match, single character", 1000) +def split_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + s1_split = s1.split + for x in _RANGE_1000: + s1_split(s2, 1) + + at bench('("A"*1000).split("B", 1)', "no match, single character", 1000) +def split_test_no_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("B") + s1_split = s1.split + for x in _RANGE_1000: + s1_split(s2, 1) + + + at bench('("AB"*1000).split("AB", 1)', "early match, two characters", 1000) +def split_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + s1_split = s1.split + for x in _RANGE_1000: + s1_split(s2, 1) + + at bench('("AB"*1000).split("BC", 1)', "no match, two characters", 1000) +def split_test_no_match_two_character(STR): + s1 = STR("AB" * 1000) + s2 = STR("BC") + s1_split = s1.split + for x in _RANGE_1000: + s1_split(s2, 1) + + at bench('("AB"*300+"C").split("BC", 1)', "late match, two characters", 1000) +def split_test_slow_match_two_characters(STR): + s1 = STR("AB" * 300+"C") + s2 = STR("BC") + s1_split = s1.split + for x in _RANGE_1000: + s1_split(s2, 1) + + at bench('s="ABC"*33; ((s+"D")*500+s+"E").split(s+"E", 1)', + "late match, 100 characters", 100) +def split_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = (m+d)*500 + m+e + s2 = m+e + s1_split = s1.split + for x in _RANGE_100: + s1_split(s2, 1) + + +#### Same for rsplit(s, 1) + + at bench('("A"*1000).rsplit("A", 1)', "early match, single character", 1000) +def rsplit_test_quick_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("A") + s1_rsplit = s1.rsplit + for x in _RANGE_1000: + s1_rsplit(s2, 1) + + at bench('("A"*1000).rsplit("B", 1)', "no match, single character", 1000) +def rsplit_test_no_match_single_character(STR): + s1 = STR("A" * 1000) + s2 = STR("B") + s1_rsplit = s1.rsplit + for x in _RANGE_1000: + s1_rsplit(s2, 1) + + + at bench('("AB"*1000).rsplit("AB", 1)', "early match, two characters", 1000) +def rsplit_test_quick_match_two_characters(STR): + s1 = STR("AB" * 1000) + s2 = STR("AB") + s1_rsplit = s1.rsplit + for x in _RANGE_1000: + s1_rsplit(s2, 1) + + at bench('("AB"*1000).rsplit("BC", 1)', "no match, two characters", 1000) +def rsplit_test_no_match_two_character(STR): + s1 = STR("AB" * 1000) + s2 = STR("BC") + s1_rsplit = s1.rsplit + for x in _RANGE_1000: + s1_rsplit(s2, 1) + + at bench('("C"+"AB"*300).rsplit("CA", 1)', "late match, two characters", 1000) +def rsplit_test_slow_match_two_characters(STR): + s1 = STR("C" + "AB" * 300) + s2 = STR("CA") + s1_rsplit = s1.rsplit + for x in _RANGE_1000: + s1_rsplit(s2, 1) + + at bench('s="ABC"*33; ("E"+s+("D"+s)*500).rsplit("E"+s, 1)', + "late match, 100 characters", 100) +def rsplit_test_slow_match_100_characters(STR): + m = STR("ABC"*33) + d = STR("D") + e = STR("E") + s1 = e + m + (d+m)*500 + s2 = e + m + s1_rsplit = s1.rsplit + for x in _RANGE_100: + s1_rsplit(s2, 1) + + +#### Benchmark the operator-based methods + + at bench('"A"*10', "repeat 1 character 10 times", 1000) +def repeat_single_10_times(STR): + s = STR("A") + for x in _RANGE_1000: + s * 10 + + at bench('"A"*1000', "repeat 1 character 1000 times", 1000) +def repeat_single_1000_times(STR): + s = STR("A") + for x in _RANGE_1000: + s * 1000 + + at bench('"ABCDE"*10', "repeat 5 characters 10 times", 1000) +def repeat_5_10_times(STR): + s = STR("ABCDE") + for x in _RANGE_1000: + s * 10 + + at bench('"ABCDE"*1000', "repeat 5 characters 1000 times", 1000) +def repeat_5_1000_times(STR): + s = STR("ABCDE") + for x in _RANGE_1000: + s * 1000 + +# + for concat + + at bench('"Andrew"+"Dalke"', "concat two strings", 1000) +def concat_two_strings(STR): + s1 = STR("Andrew") + s2 = STR("Dalke") + for x in _RANGE_1000: + s1+s2 + + at bench('s1+s2+s3+s4+...+s20', "concat 20 strings of words length 4 to 15", + 1000) +def concat_many_strings(STR): + s1=STR('TIXSGYNREDCVBHJ') + s2=STR('PUMTLXBZVDO') + s3=STR('FVZNJ') + s4=STR('OGDXUW') + s5=STR('WEIMRNCOYVGHKB') + s6=STR('FCQTNMXPUZH') + s7=STR('TICZJYRLBNVUEAK') + s8=STR('REYB') + s9=STR('PWUOQ') + s10=STR('EQHCMKBS') + s11=STR('AEVDFOH') + s12=STR('IFHVD') + s13=STR('JGTCNLXWOHQ') + s14=STR('ITSKEPYLROZAWXF') + s15=STR('THEK') + s16=STR('GHPZFBUYCKMNJIT') + s17=STR('JMUZ') + s18=STR('WLZQMTB') + s19=STR('KPADCBW') + s20=STR('TNJHZQAGBU') + for x in _RANGE_1000: + (s1 + s2+ s3+ s4+ s5+ s6+ s7+ s8+ s9+s10+ + s11+s12+s13+s14+s15+s16+s17+s18+s19+s20) + + +#### Benchmark join + +def get_bytes_yielding_seq(STR, arg): + if STR is BYTES and sys.version_info >= (3,): + raise UnsupportedType + return STR(arg) + + at bench('"A".join("")', + "join empty string, with 1 character sep", 100) +def join_empty_single(STR): + sep = STR("A") + s2 = get_bytes_yielding_seq(STR, "") + sep_join = sep.join + for x in _RANGE_100: + sep_join(s2) + + at bench('"ABCDE".join("")', + "join empty string, with 5 character sep", 100) +def join_empty_5(STR): + sep = STR("ABCDE") + s2 = get_bytes_yielding_seq(STR, "") + sep_join = sep.join + for x in _RANGE_100: + sep_join(s2) + + at bench('"A".join("ABC..Z")', + "join string with 26 characters, with 1 character sep", 1000) +def join_alphabet_single(STR): + sep = STR("A") + s2 = get_bytes_yielding_seq(STR, "ABCDEFGHIJKLMnOPQRSTUVWXYZ") + sep_join = sep.join + for x in _RANGE_1000: + sep_join(s2) + + at bench('"ABCDE".join("ABC..Z")', + "join string with 26 characters, with 5 character sep", 1000) +def join_alphabet_5(STR): + sep = STR("ABCDE") + s2 = get_bytes_yielding_seq(STR, "ABCDEFGHIJKLMnOPQRSTUVWXYZ") + sep_join = sep.join + for x in _RANGE_1000: + sep_join(s2) + + at bench('"A".join(list("ABC..Z"))', + "join list of 26 characters, with 1 character sep", 1000) +def join_alphabet_list_single(STR): + sep = STR("A") + s2 = [STR(x) for x in "ABCDEFGHIJKLMnOPQRSTUVWXYZ"] + sep_join = sep.join + for x in _RANGE_1000: + sep_join(s2) + + at bench('"ABCDE".join(list("ABC..Z"))', + "join list of 26 characters, with 5 character sep", 1000) +def join_alphabet_list_five(STR): + sep = STR("ABCDE") + s2 = [STR(x) for x in "ABCDEFGHIJKLMnOPQRSTUVWXYZ"] + sep_join = sep.join + for x in _RANGE_1000: + sep_join(s2) + + at bench('"A".join(["Bob"]*100))', + "join list of 100 words, with 1 character sep", 1000) +def join_100_words_single(STR): + sep = STR("A") + s2 = [STR("Bob")]*100 + sep_join = sep.join + for x in _RANGE_1000: + sep_join(s2) + + at bench('"ABCDE".join(["Bob"]*100))', + "join list of 100 words, with 5 character sep", 1000) +def join_100_words_5(STR): + sep = STR("ABCDE") + s2 = [STR("Bob")]*100 + sep_join = sep.join + for x in _RANGE_1000: + sep_join(s2) + +#### split tests + + at bench('("Here are some words. "*2).split()', "split whitespace (small)", 1000) +def whitespace_split(STR): + s = STR("Here are some words. "*2) + s_split = s.split + for x in _RANGE_1000: + s_split() + + at bench('("Here are some words. "*2).rsplit()', "split whitespace (small)", 1000) +def whitespace_rsplit(STR): + s = STR("Here are some words. "*2) + s_rsplit = s.rsplit + for x in _RANGE_1000: + s_rsplit() + + at bench('("Here are some words. "*2).split(None, 1)', + "split 1 whitespace", 1000) +def whitespace_split_1(STR): + s = STR("Here are some words. "*2) + s_split = s.split + N = None + for x in _RANGE_1000: + s_split(N, 1) + + at bench('("Here are some words. "*2).rsplit(None, 1)', + "split 1 whitespace", 1000) +def whitespace_rsplit_1(STR): + s = STR("Here are some words. "*2) + s_rsplit = s.rsplit + N = None + for x in _RANGE_1000: + s_rsplit(N, 1) + + at bench('("Here are some words. "*2).partition(" ")', + "split 1 whitespace", 1000) +def whitespace_partition(STR): + sep = STR(" ") + s = STR("Here are some words. "*2) + s_partition = s.partition + for x in _RANGE_1000: + s_partition(sep) + + at bench('("Here are some words. "*2).rpartition(" ")', + "split 1 whitespace", 1000) +def whitespace_rpartition(STR): + sep = STR(" ") + s = STR("Here are some words. "*2) + s_rpartition = s.rpartition + for x in _RANGE_1000: + s_rpartition(sep) + +human_text = """\ +Python is a dynamic object-oriented programming language that can be +used for many kinds of software development. It offers strong support +for integration with other languages and tools, comes with extensive +standard libraries, and can be learned in a few days. Many Python +programmers report substantial productivity gains and feel the language +encourages the development of higher quality, more maintainable code. + +Python runs on Windows, Linux/Unix, Mac OS X, OS/2, Amiga, Palm +Handhelds, and Nokia mobile phones. Python has also been ported to the +Java and .NET virtual machines. + +Python is distributed under an OSI-approved open source license that +makes it free to use, even for commercial products. +"""*25 +human_text_bytes = bytes_from_str(human_text) +human_text_unicode = unicode_from_str(human_text) +def _get_human_text(STR): + if STR is UNICODE: + return human_text_unicode + if STR is BYTES: + return human_text_bytes + raise AssertionError + + at bench('human_text.split()', "split whitespace (huge)", 10) +def whitespace_split_huge(STR): + s = _get_human_text(STR) + s_split = s.split + for x in _RANGE_10: + s_split() + + at bench('human_text.rsplit()', "split whitespace (huge)", 10) +def whitespace_rsplit_huge(STR): + s = _get_human_text(STR) + s_rsplit = s.rsplit + for x in _RANGE_10: + s_rsplit() + + + + at bench('"this\\nis\\na\\ntest\\n".split("\\n")', "split newlines", 1000) +def newlines_split(STR): + s = STR("this\nis\na\ntest\n") + s_split = s.split + nl = STR("\n") + for x in _RANGE_1000: + s_split(nl) + + + at bench('"this\\nis\\na\\ntest\\n".rsplit("\\n")', "split newlines", 1000) +def newlines_rsplit(STR): + s = STR("this\nis\na\ntest\n") + s_rsplit = s.rsplit + nl = STR("\n") + for x in _RANGE_1000: + s_rsplit(nl) + + at bench('"this\\nis\\na\\ntest\\n".splitlines()', "split newlines", 1000) +def newlines_splitlines(STR): + s = STR("this\nis\na\ntest\n") + s_splitlines = s.splitlines + for x in _RANGE_1000: + s_splitlines() + +## split text with 2000 newlines + +def _make_2000_lines(): + import random + r = random.Random(100) + chars = list(map(chr, range(32, 128))) + i = 0 + while i < len(chars): + chars[i] = " " + i += r.randrange(9) + s = "".join(chars) + s = s*4 + words = [] + for i in range(2000): + start = r.randrange(96) + n = r.randint(5, 65) + words.append(s[start:start+n]) + return "\n".join(words)+"\n" + +_text_with_2000_lines = _make_2000_lines() +_text_with_2000_lines_bytes = bytes_from_str(_text_with_2000_lines) +_text_with_2000_lines_unicode = unicode_from_str(_text_with_2000_lines) +def _get_2000_lines(STR): + if STR is UNICODE: + return _text_with_2000_lines_unicode + if STR is BYTES: + return _text_with_2000_lines_bytes + raise AssertionError + + + at bench('"...text...".split("\\n")', "split 2000 newlines", 10) +def newlines_split_2000(STR): + s = _get_2000_lines(STR) + s_split = s.split + nl = STR("\n") + for x in _RANGE_10: + s_split(nl) + + at bench('"...text...".rsplit("\\n")', "split 2000 newlines", 10) +def newlines_rsplit_2000(STR): + s = _get_2000_lines(STR) + s_rsplit = s.rsplit + nl = STR("\n") + for x in _RANGE_10: + s_rsplit(nl) + + at bench('"...text...".splitlines()', "split 2000 newlines", 10) +def newlines_splitlines_2000(STR): + s = _get_2000_lines(STR) + s_splitlines = s.splitlines + for x in _RANGE_10: + s_splitlines() + + +## split text on "--" characters + at bench( + '"this--is--a--test--of--the--emergency--broadcast--system".split("--")', + "split on multicharacter separator (small)", 1000) +def split_multichar_sep_small(STR): + s = STR("this--is--a--test--of--the--emergency--broadcast--system") + s_split = s.split + pat = STR("--") + for x in _RANGE_1000: + s_split(pat) + at bench( + '"this--is--a--test--of--the--emergency--broadcast--system".rsplit("--")', + "split on multicharacter separator (small)", 1000) +def rsplit_multichar_sep_small(STR): + s = STR("this--is--a--test--of--the--emergency--broadcast--system") + s_rsplit = s.rsplit + pat = STR("--") + for x in _RANGE_1000: + s_rsplit(pat) + +## split dna text on "ACTAT" characters + at bench('dna.split("ACTAT")', + "split on multicharacter separator (dna)", 10) +def split_multichar_sep_dna(STR): + s = _get_dna(STR) + s_split = s.split + pat = STR("ACTAT") + for x in _RANGE_10: + s_split(pat) + + at bench('dna.rsplit("ACTAT")', + "split on multicharacter separator (dna)", 10) +def rsplit_multichar_sep_dna(STR): + s = _get_dna(STR) + s_rsplit = s.rsplit + pat = STR("ACTAT") + for x in _RANGE_10: + s_rsplit(pat) + + + +## split with limits + +GFF3_example = "\t".join([ + "I", "Genomic_canonical", "region", "357208", "396183", ".", "+", ".", + "ID=Sequence:R119;note=Clone R119%3B Genbank AF063007;Name=R119"]) + + at bench('GFF3_example.split("\\t")', "tab split", 1000) +def tab_split_no_limit(STR): + sep = STR("\t") + s = STR(GFF3_example) + s_split = s.split + for x in _RANGE_1000: + s_split(sep) + + at bench('GFF3_example.split("\\t", 8)', "tab split", 1000) +def tab_split_limit(STR): + sep = STR("\t") + s = STR(GFF3_example) + s_split = s.split + for x in _RANGE_1000: + s_split(sep, 8) + + at bench('GFF3_example.rsplit("\\t")', "tab split", 1000) +def tab_rsplit_no_limit(STR): + sep = STR("\t") + s = STR(GFF3_example) + s_rsplit = s.rsplit + for x in _RANGE_1000: + s_rsplit(sep) + + at bench('GFF3_example.rsplit("\\t", 8)', "tab split", 1000) +def tab_rsplit_limit(STR): + sep = STR("\t") + s = STR(GFF3_example) + s_rsplit = s.rsplit + for x in _RANGE_1000: + s_rsplit(sep, 8) + +#### Count characters + + at bench('...text.with.2000.newlines.count("\\n")', + "count newlines", 10) +def count_newlines(STR): + s = _get_2000_lines(STR) + s_count = s.count + nl = STR("\n") + for x in _RANGE_10: + s_count(nl) + +# Orchid sequences concatenated, from Biopython +_dna = """ +CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGTTGAGATCACATAATAATTGATCGGGTT +AATCTGGAGGATCTGTTTACTTTGGTCACCCATGAGCATTTGCTGTTGAAGTGACCTAGAATTGCCATCG +AGCCTCCTTGGGAGCTTTCTTGTTGGCGAGATCTAAACCCTTGCCCGGCGCAGTTTTGCTCCAAGTCGTT +TGACACATAATTGGTGAAGGGGGTGGCATCCTTCCCTGACCCTCCCCCAACTATTTTTTTAACAACTCTC +AGCAACGGAGACTCAGTCTTCGGCAAATGCGATAAATGGTGTGAATTGCAGAATCCCGTGCACCATCGAG +TCTTTGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCACGCCTGCCTGGGCATTGCGAGTCATAT +CTCTCCCTTAACGAGGCTGTCCATACATACTGTTCAGCCGGTGCGGATGTGAGTTTGGCCCCTTGTTCTT +TGGTACGGGGGGTCTAAGAGCTGCATGGGCTTTTGATGGTCCTAAATACGGCAAGAGGTGGACGAACTAT +GCTACAACAAAATTGTTGTGCAGAGGCCCCGGGTTGTCGTATTAGATGGGCCACCGTAATCTGAAGACCC +TTTTGAACCCCATTGGAGGCCCATCAACCCATGATCAGTTGATGGCCATTTGGTTGCGACCCCAGGTCAG +GTGAGCAACAGCTGTCGTAACAAGGTTTCCGTAGGGTGAACTGCGGAAGGATCATTGTTGAGATCACATA +ATAATTGATCGAGTTAATCTGGAGGATCTGTTTACTTGGGTCACCCATGGGCATTTGCTGTTGAAGTGAC +CTAGATTTGCCATCGAGCCTCCTTGGGAGCATCCTTGTTGGCGATATCTAAACCCTCAATTTTTCCCCCA +ATCAAATTACACAAAATTGGTGGAGGGGGTGGCATTCTTCCCTTACCCTCCCCCAAATATTTTTTTAACA +ACTCTCAGCAACGGATATCTCAGCTCTTGCATCGATGAAGAACCCACCGAAATGCGATAAATGGTGTGAA +TTGCAGAATCCCGTGAACCATCGAGTCTTTGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCACG +CCTGCCTGGGCATTGCGAGTCATATCTCTCCCTTAACGAGGCTGTCCATACATACTGTTCAGCCGGTGCG +GATGTGAGTTTGGCCCCTTGTTCTTTGGTACGGGGGGTCTAAGAGATGCATGGGCTTTTGATGGTCCTAA +ATACGGCAAGAGGTGGACGAACTATGCTACAACAAAATTGTTGTGCAAAGGCCCCGGGTTGTCGTATAAG +ATGGGCCACCGATATCTGAAGACCCTTTTGGACCCCATTGGAGCCCATCAACCCATGTCAGTTGATGGCC +ATTCGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGTTGAGATCACATAATAATTGATCGA +GTTAATCTGGAGGATCTGTTTACTTGGGTCACCCATGGGCATTTGCTGTTGAAGTGACCTAGATTTGCCA +TCGAGCCTCCTTGGGAGCTTTCTTGTTGGCGATATCTAAACCCTTGCCCGGCAGAGTTTTGGGAATCCCG +TGAACCATCGAGTCTTTGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCACGCCTGCCTGGGCAT +TGCGAGTCATATCTCTCCCTTAACGAGGCTGTCCATACACACCTGTTCAGCCGGTGCGGATGTGAGTTTG +GCCCCTTGTTCTTTGGTACGGGGGGTCTAAGAGCTGCATGGGCTTTTGATGGTCCTAAATACGGCAAGAG +GTGGACGAACTATGCTACAACAAAATTGTTGTGCAAAGGCCCCGGGTTGTCGTATTAGATGGGCCACCAT +AATCTGAAGACCCTTTTGAACCCCATTGGAGGCCCATCAACCCATGATCAGTTGATGGCCATTTGGTTGC +GACCCAGTCAGGTGAGGGTAGGTGAACCTGCGGAAGGATCATTGTTGAGATCACATAATAATTGATCGAG +TTAATCTGGAGGATCTGTTTACTTTGGTCACCCATGGGCATTTGCTGTTGAAGTGACCTAGATTTGCCAT +CGAGCCTCCTTGGGAGCTTTCTTGTTGGCGAGATCTAAACCCTTGCCCGGCGGAGTTTGGCGCCAAGTCA +TATGACACATAATTGGTGAAGGGGGTGGCATCCTGCCCTGACCCTCCCCAAATTATTTTTTTAACAACTC +TCAGCAACGGATATCTCGGCTCTTGCATCGATGAAGAACGCAGCGAAATGCGATAAATGGTGTGAATTGC +AGAATCCCGTGAACCATCGAGTCTTTGGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCACGCCT +GCCTGGGCATTGGGAATCATATCTCTCCCCTAACGAGGCTATCCAAACATACTGTTCATCCGGTGCGGAT +GTGAGTTTGGCCCCTTGTTCTTTGGTACCGGGGGTCTAAGAGCTGCATGGGCATTTGATGGTCCTCAAAA +CGGCAAGAGGTGGACGAACTATGCCACAACAAAATTGTTGTCCCAAGGCCCCGGGTTGTCGTATTAGATG +GGCCACCGTAACCTGAAGACCCTTTTGAACCCCATTGGAGGCCCATCAACCCATGATCAGTTGATGACCA +TTTGTTGCGACCCCAGTCAGCTGAGCAACCCGCTGAGTGGAAGGTCATTGCCGATATCACATAATAATTG +ATCGAGTTAATCTGGAGGATCTGTTTACTTGGTCACCCATGAGCATTTGCTGTTGAAGTGACCTAGATTT +GCCATCGAGCCTCCTTGGGAGTTTTCTTGTTGGCGAGATCTAAACCCTTGCCCGGCGGAGTTGTGCGCCA +AGTCATATGACACATAATTGGTGAAGGGGGTGGCATCCTGCCCTGACCCTCCCCAAATTATTTTTTTAAC +AACTCTCAGCAACGGATATCTCGGCTCTTGCATCGATGAAGAACGCAGCGAAATGCGATAAATGGTGTGA +ATTGCAGAATCCCGTGAACCATCGAGTCTTTGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCAC +GCCTGCCTGGGCATTGCGAGTCATATCTCTCCCTTAACGAGGCTGTCCATACATACTGTTCATCCGGTGC +GGATGTGAGTTTGGCCCCTTGTTCTTTGGTACGGGGGGTCTAAGAGCTGCATGGGCATTTGATGGTCCTC +AAAACGGCAAGAGGTGGACGAACTATGCTACAACCAAATTGTTGTCCCAAGGCCCCGGGTTGTCGTATTA +GATGGGCCACCGTAACCTGAAGACCCTTTTGAACCCCATTGGAGGCCCATCAACCCATGATCAGTTGATG +ACCATGTGTTGCGACCCCAGTCAGCTGAGCAACGCGCTGAGCGTAACAAGGTTTCCGTAGGTGGACCTCC +GGGAGGATCATTGTTGAGATCACATAATAATTGATCGAGGTAATCTGGAGGATCTGCATATTTTGGTCAC +""" +_dna = "".join(_dna.splitlines()) +_dna = _dna * 25 +_dna_bytes = bytes_from_str(_dna) +_dna_unicode = unicode_from_str(_dna) + +def _get_dna(STR): + if STR is UNICODE: + return _dna_unicode + if STR is BYTES: + return _dna_bytes + raise AssertionError + + at bench('dna.count("AACT")', "count AACT substrings in DNA example", 10) +def count_aact(STR): + seq = _get_dna(STR) + seq_count = seq.count + needle = STR("AACT") + for x in _RANGE_10: + seq_count(needle) + +##### startswith and endswith + + at bench('"Andrew".startswith("A")', 'startswith single character', 1000) +def startswith_single(STR): + s1 = STR("Andrew") + s2 = STR("A") + s1_startswith = s1.startswith + for x in _RANGE_1000: + s1_startswith(s2) + + at bench('"Andrew".startswith("Andrew")', 'startswith multiple characters', + 1000) +def startswith_multiple(STR): + s1 = STR("Andrew") + s2 = STR("Andrew") + s1_startswith = s1.startswith + for x in _RANGE_1000: + s1_startswith(s2) + + at bench('"Andrew".startswith("Anders")', + 'startswith multiple characters - not!', 1000) +def startswith_multiple_not(STR): + s1 = STR("Andrew") + s2 = STR("Anders") + s1_startswith = s1.startswith + for x in _RANGE_1000: + s1_startswith(s2) + + +# endswith + + at bench('"Andrew".endswith("w")', 'endswith single character', 1000) +def endswith_single(STR): + s1 = STR("Andrew") + s2 = STR("w") + s1_endswith = s1.endswith + for x in _RANGE_1000: + s1_endswith(s2) + + at bench('"Andrew".endswith("Andrew")', 'endswith multiple characters', 1000) +def endswith_multiple(STR): + s1 = STR("Andrew") + s2 = STR("Andrew") + s1_endswith = s1.endswith + for x in _RANGE_1000: + s1_endswith(s2) + + at bench('"Andrew".endswith("Anders")', + 'endswith multiple characters - not!', 1000) +def endswith_multiple_not(STR): + s1 = STR("Andrew") + s2 = STR("Anders") + s1_endswith = s1.endswith + for x in _RANGE_1000: + s1_endswith(s2) + +#### Strip + + at bench('"Hello!\\n".strip()', 'strip terminal newline', 1000) +def terminal_newline_strip_right(STR): + s = STR("Hello!\n") + s_strip = s.strip + for x in _RANGE_1000: + s_strip() + + at bench('"Hello!\\n".rstrip()', 'strip terminal newline', 1000) +def terminal_newline_rstrip(STR): + s = STR("Hello!\n") + s_rstrip = s.rstrip + for x in _RANGE_1000: + s_rstrip() + + at bench('"\\nHello!".strip()', 'strip terminal newline', 1000) +def terminal_newline_strip_left(STR): + s = STR("\nHello!") + s_strip = s.strip + for x in _RANGE_1000: + s_strip() + + at bench('"\\nHello!\\n".strip()', 'strip terminal newline', 1000) +def terminal_newline_strip_both(STR): + s = STR("\nHello!\n") + s_strip = s.strip + for x in _RANGE_1000: + s_strip() + + at bench('"\\nHello!".rstrip()', 'strip terminal newline', 1000) +def terminal_newline_lstrip(STR): + s = STR("\nHello!") + s_lstrip = s.lstrip + for x in _RANGE_1000: + s_lstrip() + + at bench('s="Hello!\\n"; s[:-1] if s[-1]=="\\n" else s', + 'strip terminal newline', 1000) +def terminal_newline_if_else(STR): + s = STR("Hello!\n") + NL = STR("\n") + for x in _RANGE_1000: + s[:-1] if (s[-1] == NL) else s + + +# Strip multiple spaces or tabs + + at bench('"Hello\\t \\t".strip()', 'strip terminal spaces and tabs', 1000) +def terminal_space_strip(STR): + s = STR("Hello\t \t!") + s_strip = s.strip + for x in _RANGE_1000: + s_strip() + + at bench('"Hello\\t \\t".rstrip()', 'strip terminal spaces and tabs', 1000) +def terminal_space_rstrip(STR): + s = STR("Hello!\t \t") + s_rstrip = s.rstrip + for x in _RANGE_1000: + s_rstrip() + + at bench('"\\t \\tHello".rstrip()', 'strip terminal spaces and tabs', 1000) +def terminal_space_lstrip(STR): + s = STR("\t \tHello!") + s_lstrip = s.lstrip + for x in _RANGE_1000: + s_lstrip() + + +#### replace + at bench('"This is a test".replace(" ", "\\t")', 'replace single character', + 1000) +def replace_single_character(STR): + s = STR("This is a test!") + from_str = STR(" ") + to_str = STR("\t") + s_replace = s.replace + for x in _RANGE_1000: + s_replace(from_str, to_str) + + at uses_re + at bench('re.sub(" ", "\\t", "This is a test"', 'replace single character', + 1000) +def replace_single_character_re(STR): + s = STR("This is a test!") + pat = re.compile(STR(" ")) + to_str = STR("\t") + pat_sub = pat.sub + for x in _RANGE_1000: + pat_sub(to_str, s) + + at bench('"...text.with.2000.lines...replace("\\n", " ")', + 'replace single character, big string', 10) +def replace_single_character_big(STR): + s = _get_2000_lines(STR) + from_str = STR("\n") + to_str = STR(" ") + s_replace = s.replace + for x in _RANGE_10: + s_replace(from_str, to_str) + + at uses_re + at bench('re.sub("\\n", " ", "...text.with.2000.lines...")', + 'replace single character, big string', 10) +def replace_single_character_big_re(STR): + s = _get_2000_lines(STR) + pat = re.compile(STR("\n")) + to_str = STR(" ") + pat_sub = pat.sub + for x in _RANGE_10: + pat_sub(to_str, s) + + + at bench('dna.replace("ATC", "ATT")', + 'replace multiple characters, dna', 10) +def replace_multiple_characters_dna(STR): + seq = _get_dna(STR) + from_str = STR("ATC") + to_str = STR("ATT") + seq_replace = seq.replace + for x in _RANGE_10: + seq_replace(from_str, to_str) + +# This increases the character count + at bench('"...text.with.2000.newlines...replace("\\n", "\\r\\n")', + 'replace and expand multiple characters, big string', 10) +def replace_multiple_character_big(STR): + s = _get_2000_lines(STR) + from_str = STR("\n") + to_str = STR("\r\n") + s_replace = s.replace + for x in _RANGE_10: + s_replace(from_str, to_str) + + +# This decreases the character count + at bench('"When shall we three meet again?".replace("ee", "")', + 'replace/remove multiple characters', 1000) +def replace_multiple_character_remove(STR): + s = STR("When shall we three meet again?") + from_str = STR("ee") + to_str = STR("") + s_replace = s.replace + for x in _RANGE_1000: + s_replace(from_str, to_str) + + +big_s = "A" + ("Z"*128*1024) +big_s_bytes = bytes_from_str(big_s) +big_s_unicode = unicode_from_str(big_s) +def _get_big_s(STR): + if STR is UNICODE: return big_s_unicode + if STR is BYTES: return big_s_bytes + raise AssertionError + +# The older replace implementation counted all matches in +# the string even when it only neeed to make one replacement. + at bench('("A" + ("Z"*128*1024)).replace("A", "BB", 1)', + 'quick replace single character match', 10) +def quick_replace_single_match(STR): + s = _get_big_s(STR) + from_str = STR("A") + to_str = STR("BB") + s_replace = s.replace + for x in _RANGE_10: + s_replace(from_str, to_str, 1) + + at bench('("A" + ("Z"*128*1024)).replace("AZZ", "BBZZ", 1)', + 'quick replace multiple character match', 10) +def quick_replace_multiple_match(STR): + s = _get_big_s(STR) + from_str = STR("AZZ") + to_str = STR("BBZZ") + s_replace = s.replace + for x in _RANGE_10: + s_replace(from_str, to_str, 1) + + +#### + +# CCP does a lot of this, for internationalisation of ingame messages. +_format = "The %(thing)s is %(place)s the %(location)s." +_format_dict = { "thing":"THING", "place":"PLACE", "location":"LOCATION", } +_format_bytes = bytes_from_str(_format) +_format_unicode = unicode_from_str(_format) +_format_dict_bytes = dict((bytes_from_str(k), bytes_from_str(v)) for (k,v) in _format_dict.items()) +_format_dict_unicode = dict((unicode_from_str(k), unicode_from_str(v)) for (k,v) in _format_dict.items()) + +def _get_format(STR): + if STR is UNICODE: + return _format_unicode + if STR is BYTES: + if sys.version_info >= (3,): + raise UnsupportedType + return _format_bytes + raise AssertionError + +def _get_format_dict(STR): + if STR is UNICODE: + return _format_dict_unicode + if STR is BYTES: + if sys.version_info >= (3,): + raise UnsupportedType + return _format_dict_bytes + raise AssertionError + +# Formatting. + at bench('"The %(k1)s is %(k2)s the %(k3)s."%{"k1":"x","k2":"y","k3":"z",}', + 'formatting a string type with a dict', 1000) +def format_with_dict(STR): + s = _get_format(STR) + d = _get_format_dict(STR) + for x in _RANGE_1000: + s % d + + +#### Upper- and lower- case conversion + + at bench('("Where in the world is Carmen San Deigo?"*10).lower()', + "case conversion -- rare", 1000) +def lower_conversion_rare(STR): + s = STR("Where in the world is Carmen San Deigo?"*10) + s_lower = s.lower + for x in _RANGE_1000: + s_lower() + + at bench('("WHERE IN THE WORLD IS CARMEN SAN DEIGO?"*10).lower()', + "case conversion -- dense", 1000) +def lower_conversion_dense(STR): + s = STR("WHERE IN THE WORLD IS CARMEN SAN DEIGO?"*10) + s_lower = s.lower + for x in _RANGE_1000: + s_lower() + + + at bench('("wHERE IN THE WORLD IS cARMEN sAN dEIGO?"*10).upper()', + "case conversion -- rare", 1000) +def upper_conversion_rare(STR): + s = STR("Where in the world is Carmen San Deigo?"*10) + s_upper = s.upper + for x in _RANGE_1000: + s_upper() + + at bench('("where in the world is carmen san deigo?"*10).upper()', + "case conversion -- dense", 1000) +def upper_conversion_dense(STR): + s = STR("where in the world is carmen san deigo?"*10) + s_upper = s.upper + for x in _RANGE_1000: + s_upper() + + +# end of benchmarks + +################# + +class BenchTimer(timeit.Timer): + def best(self, repeat=1): + for i in range(1, 10): + number = 10**i + x = self.timeit(number) + if x > 0.02: + break + times = [x] + for i in range(1, repeat): + times.append(self.timeit(number)) + return min(times) / number + +def main(): + (options, test_names) = parser.parse_args() + if options.bytes_only and options.unicode_only: + raise SystemExit("Only one of --8-bit and --unicode are allowed") + + bench_functions = [] + for (k,v) in globals().items(): + if hasattr(v, "is_bench"): + if test_names: + for name in test_names: + if name in v.group: + break + else: + # Not selected, ignore + continue + if options.skip_re and hasattr(v, "uses_re"): + continue + + bench_functions.append( (v.group, k, v) ) + bench_functions.sort() + + p("bytes\tunicode") + p("(in ms)\t(in ms)\t%\tcomment") + + bytes_total = uni_total = 0.0 + + for title, group in itertools.groupby(bench_functions, + operator.itemgetter(0)): + # Flush buffer before each group + sys.stdout.flush() + p("="*10, title) + for (_, k, v) in group: + if hasattr(v, "is_bench"): + bytes_time = 0.0 + bytes_time_s = " - " + if not options.unicode_only: + try: + bytes_time = BenchTimer("__main__.%s(__main__.BYTES)" % (k,), + "import __main__").best(REPEAT) + bytes_time_s = "%.2f" % (1000 * bytes_time) + bytes_total += bytes_time + except UnsupportedType: + bytes_time_s = "N/A" + uni_time = 0.0 + uni_time_s = " - " + if not options.bytes_only: + try: + uni_time = BenchTimer("__main__.%s(__main__.UNICODE)" % (k,), + "import __main__").best(REPEAT) + uni_time_s = "%.2f" % (1000 * uni_time) + uni_total += uni_time + except UnsupportedType: + uni_time_s = "N/A" + try: + average = bytes_time/uni_time + except (TypeError, ZeroDivisionError): + average = 0.0 + p("%s\t%s\t%.1f\t%s (*%d)" % ( + bytes_time_s, uni_time_s, 100.*average, + v.comment, v.repeat_count)) + + if bytes_total == uni_total == 0.0: + p("That was zippy!") + else: + try: + ratio = bytes_total/uni_total + except ZeroDivisionError: + ratio = 0.0 + p("%.2f\t%.2f\t%.1f\t%s" % ( + 1000*bytes_total, 1000*uni_total, 100.*ratio, + "TOTAL")) + +if __name__ == "__main__": + main() + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 17:09:48 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 17:09:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_whitespace?= Message-ID: http://hg.python.org/cpython/rev/24e0850be06d changeset: 76180:24e0850be06d user: Antoine Pitrou date: Mon Apr 09 17:04:14 2012 +0200 summary: Fix whitespace files: Tools/stringbench/stringbench.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Tools/stringbench/stringbench.py b/Tools/stringbench/stringbench.py --- a/Tools/stringbench/stringbench.py +++ b/Tools/stringbench/stringbench.py @@ -1480,4 +1480,3 @@ if __name__ == "__main__": main() - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 17:12:14 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 09 Apr 2012 17:12:14 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Update_description_of_bench?= =?utf8?q?marks_and_mention_the_benchmarks_repo?= Message-ID: http://hg.python.org/cpython/rev/f6191e14808f changeset: 76181:f6191e14808f user: Antoine Pitrou date: Mon Apr 09 17:06:44 2012 +0200 summary: Update description of benchmarks and mention the benchmarks repo files: Tools/README | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Tools/README b/Tools/README --- a/Tools/README +++ b/Tools/README @@ -3,7 +3,7 @@ buildbot Batchfiles for running on Windows buildslaves. -ccbench A Python concurrency benchmark. +ccbench A Python threads-based concurrency benchmark. (*) demo Several Python programming demos. @@ -17,13 +17,13 @@ and msgfmt.py generates a binary message catalog from a catalog in text format. -iobench Benchmark for the new Python I/O system. +iobench Benchmark for the new Python I/O system. (*) msi Support for packaging Python as an MSI package on Windows. parser Un-parsing tool to generate code from an AST. -pybench Comprehensive Python benchmarking suite. +pybench Low-level benchmarking for the Python evaluation loop. (*) pynche A Tkinter-based color editor. @@ -33,7 +33,7 @@ to Python 3 code. stringbench A suite of micro-benchmarks for various operations on - strings (both 8-bit and unicode). + strings (both 8-bit and unicode). (*) test2to3 A demonstration of how to use 2to3 transparently in setup.py. @@ -43,3 +43,6 @@ unittestgui A Tkinter based GUI test runner for unittest, with test discovery. + + +(*) A generic benchmark suite is maintained separately at http://hg.python.org/benchmarks/ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 18:07:43 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 9 Apr 2012 18:07:43 +0200 (CEST) Subject: [Python-checkins] r88940 - in sandbox/trunk/stringbench: MOVED README stringbench.py Message-ID: <3VRGcv4BwrzMNq@mail.python.org> Author: antoine.pitrou Date: Mon Apr 9 18:07:43 2012 New Revision: 88940 Log: Register that stringbench is now maintained with the rest of Python. Added: sandbox/trunk/stringbench/MOVED Removed: sandbox/trunk/stringbench/README sandbox/trunk/stringbench/stringbench.py Added: sandbox/trunk/stringbench/MOVED ============================================================================== --- (empty file) +++ sandbox/trunk/stringbench/MOVED Mon Apr 9 18:07:43 2012 @@ -0,0 +1,3 @@ +stringbench is now maintained in the CPython source tree, in the +Tools/stringbench directory. +See http://docs.python.org/devguide/setup.html#setup. Deleted: sandbox/trunk/stringbench/README ============================================================================== --- sandbox/trunk/stringbench/README Mon Apr 9 18:07:43 2012 +++ (empty file) @@ -1,68 +0,0 @@ -stringbench is a set of performance tests comparing byte string -operations with unicode operations. The two string implementations -are loosely based on each other and sometimes the algorithm for one is -faster than the other. - -These test set was started at the Need For Speed sprint in Reykjavik -to identify which string methods could be sped up quickly and to -identify obvious places for improvement. - -Here is an example of a benchmark - - - at bench('"Andrew".startswith("A")', 'startswith single character', 1000) -def startswith_single(STR): - s1 = STR("Andrew") - s2 = STR("A") - s1_startswith = s1.startswith - for x in _RANGE_1000: - s1_startswith(s2) - -The bench decorator takes three parameters. The first is a short -description of how the code works. In most cases this is Python code -snippet. It is not the code which is actually run because the real -code is hand-optimized to focus on the method being tested. - -The second parameter is a group title. All benchmarks with the same -group title are listed together. This lets you compare different -implementations of the same algorithm, such as "t in s" -vs. "s.find(t)". - -The last is a count. Each benchmark loops over the algorithm either -100 or 1000 times, depending on the algorithm performance. The output -time is the time per benchmark call so the reader needs a way to know -how to scale the performance. - -These parameters become function attributes. - - -Here is an example of the output - - -========== count newlines -38.54 41.60 92.7 ...text.with.2000.newlines.count("\n") (*100) -========== early match, single character -1.14 1.18 96.8 ("A"*1000).find("A") (*1000) -0.44 0.41 105.6 "A" in "A"*1000 (*1000) -1.15 1.17 98.1 ("A"*1000).index("A") (*1000) - -The first column is the run time in milliseconds for byte strings. -The second is the run time for unicode strings. The third is a -percentage; byte time / unicode time. It's the percentage by which -unicode is faster than byte strings. - -The last column contains the code snippet and the repeat count for the -internal benchmark loop. - -The times are computed with 'timeit.py' which repeats the test more -and more times until the total time takes over 0.2 seconds, returning -the best time for a single iteration. - -The final line of the output is the cumulative time for byte and -unicode strings, and the overall performance of unicode relative to -bytes. For example - -4079.83 5432.25 75.1 TOTAL - -However, this has no meaning as it evenly weights every test. - Deleted: sandbox/trunk/stringbench/stringbench.py ============================================================================== --- sandbox/trunk/stringbench/stringbench.py Mon Apr 9 18:07:43 2012 +++ (empty file) @@ -1,1483 +0,0 @@ - -# Various microbenchmarks comparing unicode and byte string performance -# Please keep this file both 2.x and 3.x compatible! - -import timeit -import itertools -import operator -import re -import sys -import datetime -import optparse - -VERSION = '2.0' - -def p(*args): - sys.stdout.write(' '.join(str(s) for s in args) + '\n') - -if sys.version_info >= (3,): - BYTES = bytes_from_str = lambda x: x.encode('ascii') - UNICODE = unicode_from_str = lambda x: x -else: - BYTES = bytes_from_str = lambda x: x - UNICODE = unicode_from_str = lambda x: x.decode('ascii') - -class UnsupportedType(TypeError): - pass - - -p('stringbench v%s' % VERSION) -p(sys.version) -p(datetime.datetime.now()) - -REPEAT = 1 -REPEAT = 3 -#REPEAT = 7 - -if __name__ != "__main__": - raise SystemExit("Must run as main program") - -parser = optparse.OptionParser() -parser.add_option("-R", "--skip-re", dest="skip_re", - action="store_true", - help="skip regular expression tests") -parser.add_option("-8", "--8-bit", dest="bytes_only", - action="store_true", - help="only do 8-bit string benchmarks") -parser.add_option("-u", "--unicode", dest="unicode_only", - action="store_true", - help="only do Unicode string benchmarks") - - -_RANGE_1000 = list(range(1000)) -_RANGE_100 = list(range(100)) -_RANGE_10 = list(range(10)) - -dups = {} -def bench(s, group, repeat_count): - def blah(f): - if f.__name__ in dups: - raise AssertionError("Multiple functions with same name: %r" % - (f.__name__,)) - dups[f.__name__] = 1 - f.comment = s - f.is_bench = True - f.group = group - f.repeat_count = repeat_count - return f - return blah - -def uses_re(f): - f.uses_re = True - -####### 'in' comparisons - - at bench('"A" in "A"*1000', "early match, single character", 1000) -def in_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - for x in _RANGE_1000: - s2 in s1 - - at bench('"B" in "A"*1000', "no match, single character", 1000) -def in_test_no_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("B") - for x in _RANGE_1000: - s2 in s1 - - - at bench('"AB" in "AB"*1000', "early match, two characters", 1000) -def in_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - for x in _RANGE_1000: - s2 in s1 - - at bench('"BC" in "AB"*1000', "no match, two characters", 1000) -def in_test_no_match_two_character(STR): - s1 = STR("AB" * 1000) - s2 = STR("BC") - for x in _RANGE_1000: - s2 in s1 - - at bench('"BC" in ("AB"*300+"C")', "late match, two characters", 1000) -def in_test_slow_match_two_characters(STR): - s1 = STR("AB" * 300+"C") - s2 = STR("BC") - for x in _RANGE_1000: - s2 in s1 - - at bench('s="ABC"*33; (s+"E") in ((s+"D")*300+s+"E")', - "late match, 100 characters", 100) -def in_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = (m+d)*300 + m+e - s2 = m+e - for x in _RANGE_100: - s2 in s1 - -# Try with regex - at uses_re - at bench('s="ABC"*33; re.compile(s+"D").search((s+"D")*300+s+"E")', - "late match, 100 characters", 100) -def re_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = (m+d)*300 + m+e - s2 = m+e - pat = re.compile(s2) - search = pat.search - for x in _RANGE_100: - search(s1) - - -#### same tests as 'in' but use 'find' - - at bench('("A"*1000).find("A")', "early match, single character", 1000) -def find_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - s1_find = s1.find - for x in _RANGE_1000: - s1_find(s2) - - at bench('("A"*1000).find("B")', "no match, single character", 1000) -def find_test_no_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("B") - s1_find = s1.find - for x in _RANGE_1000: - s1_find(s2) - - - at bench('("AB"*1000).find("AB")', "early match, two characters", 1000) -def find_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - s1_find = s1.find - for x in _RANGE_1000: - s1_find(s2) - - at bench('("AB"*1000).find("BC")', "no match, two characters", 1000) -def find_test_no_match_two_character(STR): - s1 = STR("AB" * 1000) - s2 = STR("BC") - s1_find = s1.find - for x in _RANGE_1000: - s1_find(s2) - - at bench('("AB"*1000).find("CA")', "no match, two characters", 1000) -def find_test_no_match_two_character_bis(STR): - s1 = STR("AB" * 1000) - s2 = STR("CA") - s1_find = s1.find - for x in _RANGE_1000: - s1_find(s2) - - at bench('("AB"*300+"C").find("BC")', "late match, two characters", 1000) -def find_test_slow_match_two_characters(STR): - s1 = STR("AB" * 300+"C") - s2 = STR("BC") - s1_find = s1.find - for x in _RANGE_1000: - s1_find(s2) - - at bench('("AB"*300+"CA").find("CA")', "late match, two characters", 1000) -def find_test_slow_match_two_characters_bis(STR): - s1 = STR("AB" * 300+"CA") - s2 = STR("CA") - s1_find = s1.find - for x in _RANGE_1000: - s1_find(s2) - - at bench('s="ABC"*33; ((s+"D")*500+s+"E").find(s+"E")', - "late match, 100 characters", 100) -def find_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = (m+d)*500 + m+e - s2 = m+e - s1_find = s1.find - for x in _RANGE_100: - s1_find(s2) - - at bench('s="ABC"*33; ((s+"D")*500+"E"+s).find("E"+s)', - "late match, 100 characters", 100) -def find_test_slow_match_100_characters_bis(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = (m+d)*500 + e+m - s2 = e+m - s1_find = s1.find - for x in _RANGE_100: - s1_find(s2) - - -#### Same tests for 'rfind' - - at bench('("A"*1000).rfind("A")', "early match, single character", 1000) -def rfind_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - s1_rfind = s1.rfind - for x in _RANGE_1000: - s1_rfind(s2) - - at bench('("A"*1000).rfind("B")', "no match, single character", 1000) -def rfind_test_no_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("B") - s1_rfind = s1.rfind - for x in _RANGE_1000: - s1_rfind(s2) - - - at bench('("AB"*1000).rfind("AB")', "early match, two characters", 1000) -def rfind_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - s1_rfind = s1.rfind - for x in _RANGE_1000: - s1_rfind(s2) - - at bench('("AB"*1000).rfind("BC")', "no match, two characters", 1000) -def rfind_test_no_match_two_character(STR): - s1 = STR("AB" * 1000) - s2 = STR("BC") - s1_rfind = s1.rfind - for x in _RANGE_1000: - s1_rfind(s2) - - at bench('("AB"*1000).rfind("CA")', "no match, two characters", 1000) -def rfind_test_no_match_two_character_bis(STR): - s1 = STR("AB" * 1000) - s2 = STR("CA") - s1_rfind = s1.rfind - for x in _RANGE_1000: - s1_rfind(s2) - - at bench('("C"+"AB"*300).rfind("CA")', "late match, two characters", 1000) -def rfind_test_slow_match_two_characters(STR): - s1 = STR("C" + "AB" * 300) - s2 = STR("CA") - s1_rfind = s1.rfind - for x in _RANGE_1000: - s1_rfind(s2) - - at bench('("BC"+"AB"*300).rfind("BC")', "late match, two characters", 1000) -def rfind_test_slow_match_two_characters_bis(STR): - s1 = STR("BC" + "AB" * 300) - s2 = STR("BC") - s1_rfind = s1.rfind - for x in _RANGE_1000: - s1_rfind(s2) - - at bench('s="ABC"*33; ("E"+s+("D"+s)*500).rfind("E"+s)', - "late match, 100 characters", 100) -def rfind_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = e+m + (d+m)*500 - s2 = e+m - s1_rfind = s1.rfind - for x in _RANGE_100: - s1_rfind(s2) - - at bench('s="ABC"*33; (s+"E"+("D"+s)*500).rfind(s+"E")', - "late match, 100 characters", 100) -def rfind_test_slow_match_100_characters_bis(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = m+e + (d+m)*500 - s2 = m+e - s1_rfind = s1.rfind - for x in _RANGE_100: - s1_rfind(s2) - - -#### Now with index. -# Skip the ones which fail because that would include exception overhead. - - at bench('("A"*1000).index("A")', "early match, single character", 1000) -def index_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - s1_index = s1.index - for x in _RANGE_1000: - s1_index(s2) - - at bench('("AB"*1000).index("AB")', "early match, two characters", 1000) -def index_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - s1_index = s1.index - for x in _RANGE_1000: - s1_index(s2) - - at bench('("AB"*300+"C").index("BC")', "late match, two characters", 1000) -def index_test_slow_match_two_characters(STR): - s1 = STR("AB" * 300+"C") - s2 = STR("BC") - s1_index = s1.index - for x in _RANGE_1000: - s1_index(s2) - - at bench('s="ABC"*33; ((s+"D")*500+s+"E").index(s+"E")', - "late match, 100 characters", 100) -def index_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = (m+d)*500 + m+e - s2 = m+e - s1_index = s1.index - for x in _RANGE_100: - s1_index(s2) - - -#### Same for rindex - - at bench('("A"*1000).rindex("A")', "early match, single character", 1000) -def rindex_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - s1_rindex = s1.rindex - for x in _RANGE_1000: - s1_rindex(s2) - - at bench('("AB"*1000).rindex("AB")', "early match, two characters", 1000) -def rindex_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - s1_rindex = s1.rindex - for x in _RANGE_1000: - s1_rindex(s2) - - at bench('("C"+"AB"*300).rindex("CA")', "late match, two characters", 1000) -def rindex_test_slow_match_two_characters(STR): - s1 = STR("C" + "AB" * 300) - s2 = STR("CA") - s1_rindex = s1.rindex - for x in _RANGE_1000: - s1_rindex(s2) - - at bench('s="ABC"*33; ("E"+s+("D"+s)*500).rindex("E"+s)', - "late match, 100 characters", 100) -def rindex_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = e + m + (d+m)*500 - s2 = e + m - s1_rindex = s1.rindex - for x in _RANGE_100: - s1_rindex(s2) - - -#### Same for partition - - at bench('("A"*1000).partition("A")', "early match, single character", 1000) -def partition_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - s1_partition = s1.partition - for x in _RANGE_1000: - s1_partition(s2) - - at bench('("A"*1000).partition("B")', "no match, single character", 1000) -def partition_test_no_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("B") - s1_partition = s1.partition - for x in _RANGE_1000: - s1_partition(s2) - - - at bench('("AB"*1000).partition("AB")', "early match, two characters", 1000) -def partition_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - s1_partition = s1.partition - for x in _RANGE_1000: - s1_partition(s2) - - at bench('("AB"*1000).partition("BC")', "no match, two characters", 1000) -def partition_test_no_match_two_character(STR): - s1 = STR("AB" * 1000) - s2 = STR("BC") - s1_partition = s1.partition - for x in _RANGE_1000: - s1_partition(s2) - - at bench('("AB"*300+"C").partition("BC")', "late match, two characters", 1000) -def partition_test_slow_match_two_characters(STR): - s1 = STR("AB" * 300+"C") - s2 = STR("BC") - s1_partition = s1.partition - for x in _RANGE_1000: - s1_partition(s2) - - at bench('s="ABC"*33; ((s+"D")*500+s+"E").partition(s+"E")', - "late match, 100 characters", 100) -def partition_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = (m+d)*500 + m+e - s2 = m+e - s1_partition = s1.partition - for x in _RANGE_100: - s1_partition(s2) - - -#### Same for rpartition - - at bench('("A"*1000).rpartition("A")', "early match, single character", 1000) -def rpartition_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - s1_rpartition = s1.rpartition - for x in _RANGE_1000: - s1_rpartition(s2) - - at bench('("A"*1000).rpartition("B")', "no match, single character", 1000) -def rpartition_test_no_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("B") - s1_rpartition = s1.rpartition - for x in _RANGE_1000: - s1_rpartition(s2) - - - at bench('("AB"*1000).rpartition("AB")', "early match, two characters", 1000) -def rpartition_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - s1_rpartition = s1.rpartition - for x in _RANGE_1000: - s1_rpartition(s2) - - at bench('("AB"*1000).rpartition("BC")', "no match, two characters", 1000) -def rpartition_test_no_match_two_character(STR): - s1 = STR("AB" * 1000) - s2 = STR("BC") - s1_rpartition = s1.rpartition - for x in _RANGE_1000: - s1_rpartition(s2) - - at bench('("C"+"AB"*300).rpartition("CA")', "late match, two characters", 1000) -def rpartition_test_slow_match_two_characters(STR): - s1 = STR("C" + "AB" * 300) - s2 = STR("CA") - s1_rpartition = s1.rpartition - for x in _RANGE_1000: - s1_rpartition(s2) - - at bench('s="ABC"*33; ("E"+s+("D"+s)*500).rpartition("E"+s)', - "late match, 100 characters", 100) -def rpartition_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = e + m + (d+m)*500 - s2 = e + m - s1_rpartition = s1.rpartition - for x in _RANGE_100: - s1_rpartition(s2) - - -#### Same for split(s, 1) - - at bench('("A"*1000).split("A", 1)', "early match, single character", 1000) -def split_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - s1_split = s1.split - for x in _RANGE_1000: - s1_split(s2, 1) - - at bench('("A"*1000).split("B", 1)', "no match, single character", 1000) -def split_test_no_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("B") - s1_split = s1.split - for x in _RANGE_1000: - s1_split(s2, 1) - - - at bench('("AB"*1000).split("AB", 1)', "early match, two characters", 1000) -def split_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - s1_split = s1.split - for x in _RANGE_1000: - s1_split(s2, 1) - - at bench('("AB"*1000).split("BC", 1)', "no match, two characters", 1000) -def split_test_no_match_two_character(STR): - s1 = STR("AB" * 1000) - s2 = STR("BC") - s1_split = s1.split - for x in _RANGE_1000: - s1_split(s2, 1) - - at bench('("AB"*300+"C").split("BC", 1)', "late match, two characters", 1000) -def split_test_slow_match_two_characters(STR): - s1 = STR("AB" * 300+"C") - s2 = STR("BC") - s1_split = s1.split - for x in _RANGE_1000: - s1_split(s2, 1) - - at bench('s="ABC"*33; ((s+"D")*500+s+"E").split(s+"E", 1)', - "late match, 100 characters", 100) -def split_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = (m+d)*500 + m+e - s2 = m+e - s1_split = s1.split - for x in _RANGE_100: - s1_split(s2, 1) - - -#### Same for rsplit(s, 1) - - at bench('("A"*1000).rsplit("A", 1)', "early match, single character", 1000) -def rsplit_test_quick_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("A") - s1_rsplit = s1.rsplit - for x in _RANGE_1000: - s1_rsplit(s2, 1) - - at bench('("A"*1000).rsplit("B", 1)', "no match, single character", 1000) -def rsplit_test_no_match_single_character(STR): - s1 = STR("A" * 1000) - s2 = STR("B") - s1_rsplit = s1.rsplit - for x in _RANGE_1000: - s1_rsplit(s2, 1) - - - at bench('("AB"*1000).rsplit("AB", 1)', "early match, two characters", 1000) -def rsplit_test_quick_match_two_characters(STR): - s1 = STR("AB" * 1000) - s2 = STR("AB") - s1_rsplit = s1.rsplit - for x in _RANGE_1000: - s1_rsplit(s2, 1) - - at bench('("AB"*1000).rsplit("BC", 1)', "no match, two characters", 1000) -def rsplit_test_no_match_two_character(STR): - s1 = STR("AB" * 1000) - s2 = STR("BC") - s1_rsplit = s1.rsplit - for x in _RANGE_1000: - s1_rsplit(s2, 1) - - at bench('("C"+"AB"*300).rsplit("CA", 1)', "late match, two characters", 1000) -def rsplit_test_slow_match_two_characters(STR): - s1 = STR("C" + "AB" * 300) - s2 = STR("CA") - s1_rsplit = s1.rsplit - for x in _RANGE_1000: - s1_rsplit(s2, 1) - - at bench('s="ABC"*33; ("E"+s+("D"+s)*500).rsplit("E"+s, 1)', - "late match, 100 characters", 100) -def rsplit_test_slow_match_100_characters(STR): - m = STR("ABC"*33) - d = STR("D") - e = STR("E") - s1 = e + m + (d+m)*500 - s2 = e + m - s1_rsplit = s1.rsplit - for x in _RANGE_100: - s1_rsplit(s2, 1) - - -#### Benchmark the operator-based methods - - at bench('"A"*10', "repeat 1 character 10 times", 1000) -def repeat_single_10_times(STR): - s = STR("A") - for x in _RANGE_1000: - s * 10 - - at bench('"A"*1000', "repeat 1 character 1000 times", 1000) -def repeat_single_1000_times(STR): - s = STR("A") - for x in _RANGE_1000: - s * 1000 - - at bench('"ABCDE"*10', "repeat 5 characters 10 times", 1000) -def repeat_5_10_times(STR): - s = STR("ABCDE") - for x in _RANGE_1000: - s * 10 - - at bench('"ABCDE"*1000', "repeat 5 characters 1000 times", 1000) -def repeat_5_1000_times(STR): - s = STR("ABCDE") - for x in _RANGE_1000: - s * 1000 - -# + for concat - - at bench('"Andrew"+"Dalke"', "concat two strings", 1000) -def concat_two_strings(STR): - s1 = STR("Andrew") - s2 = STR("Dalke") - for x in _RANGE_1000: - s1+s2 - - at bench('s1+s2+s3+s4+...+s20', "concat 20 strings of words length 4 to 15", - 1000) -def concat_many_strings(STR): - s1=STR('TIXSGYNREDCVBHJ') - s2=STR('PUMTLXBZVDO') - s3=STR('FVZNJ') - s4=STR('OGDXUW') - s5=STR('WEIMRNCOYVGHKB') - s6=STR('FCQTNMXPUZH') - s7=STR('TICZJYRLBNVUEAK') - s8=STR('REYB') - s9=STR('PWUOQ') - s10=STR('EQHCMKBS') - s11=STR('AEVDFOH') - s12=STR('IFHVD') - s13=STR('JGTCNLXWOHQ') - s14=STR('ITSKEPYLROZAWXF') - s15=STR('THEK') - s16=STR('GHPZFBUYCKMNJIT') - s17=STR('JMUZ') - s18=STR('WLZQMTB') - s19=STR('KPADCBW') - s20=STR('TNJHZQAGBU') - for x in _RANGE_1000: - (s1 + s2+ s3+ s4+ s5+ s6+ s7+ s8+ s9+s10+ - s11+s12+s13+s14+s15+s16+s17+s18+s19+s20) - - -#### Benchmark join - -def get_bytes_yielding_seq(STR, arg): - if STR is BYTES and sys.version_info >= (3,): - raise UnsupportedType - return STR(arg) - - at bench('"A".join("")', - "join empty string, with 1 character sep", 100) -def join_empty_single(STR): - sep = STR("A") - s2 = get_bytes_yielding_seq(STR, "") - sep_join = sep.join - for x in _RANGE_100: - sep_join(s2) - - at bench('"ABCDE".join("")', - "join empty string, with 5 character sep", 100) -def join_empty_5(STR): - sep = STR("ABCDE") - s2 = get_bytes_yielding_seq(STR, "") - sep_join = sep.join - for x in _RANGE_100: - sep_join(s2) - - at bench('"A".join("ABC..Z")', - "join string with 26 characters, with 1 character sep", 1000) -def join_alphabet_single(STR): - sep = STR("A") - s2 = get_bytes_yielding_seq(STR, "ABCDEFGHIJKLMnOPQRSTUVWXYZ") - sep_join = sep.join - for x in _RANGE_1000: - sep_join(s2) - - at bench('"ABCDE".join("ABC..Z")', - "join string with 26 characters, with 5 character sep", 1000) -def join_alphabet_5(STR): - sep = STR("ABCDE") - s2 = get_bytes_yielding_seq(STR, "ABCDEFGHIJKLMnOPQRSTUVWXYZ") - sep_join = sep.join - for x in _RANGE_1000: - sep_join(s2) - - at bench('"A".join(list("ABC..Z"))', - "join list of 26 characters, with 1 character sep", 1000) -def join_alphabet_list_single(STR): - sep = STR("A") - s2 = [STR(x) for x in "ABCDEFGHIJKLMnOPQRSTUVWXYZ"] - sep_join = sep.join - for x in _RANGE_1000: - sep_join(s2) - - at bench('"ABCDE".join(list("ABC..Z"))', - "join list of 26 characters, with 5 character sep", 1000) -def join_alphabet_list_five(STR): - sep = STR("ABCDE") - s2 = [STR(x) for x in "ABCDEFGHIJKLMnOPQRSTUVWXYZ"] - sep_join = sep.join - for x in _RANGE_1000: - sep_join(s2) - - at bench('"A".join(["Bob"]*100))', - "join list of 100 words, with 1 character sep", 1000) -def join_100_words_single(STR): - sep = STR("A") - s2 = [STR("Bob")]*100 - sep_join = sep.join - for x in _RANGE_1000: - sep_join(s2) - - at bench('"ABCDE".join(["Bob"]*100))', - "join list of 100 words, with 5 character sep", 1000) -def join_100_words_5(STR): - sep = STR("ABCDE") - s2 = [STR("Bob")]*100 - sep_join = sep.join - for x in _RANGE_1000: - sep_join(s2) - -#### split tests - - at bench('("Here are some words. "*2).split()', "split whitespace (small)", 1000) -def whitespace_split(STR): - s = STR("Here are some words. "*2) - s_split = s.split - for x in _RANGE_1000: - s_split() - - at bench('("Here are some words. "*2).rsplit()', "split whitespace (small)", 1000) -def whitespace_rsplit(STR): - s = STR("Here are some words. "*2) - s_rsplit = s.rsplit - for x in _RANGE_1000: - s_rsplit() - - at bench('("Here are some words. "*2).split(None, 1)', - "split 1 whitespace", 1000) -def whitespace_split_1(STR): - s = STR("Here are some words. "*2) - s_split = s.split - N = None - for x in _RANGE_1000: - s_split(N, 1) - - at bench('("Here are some words. "*2).rsplit(None, 1)', - "split 1 whitespace", 1000) -def whitespace_rsplit_1(STR): - s = STR("Here are some words. "*2) - s_rsplit = s.rsplit - N = None - for x in _RANGE_1000: - s_rsplit(N, 1) - - at bench('("Here are some words. "*2).partition(" ")', - "split 1 whitespace", 1000) -def whitespace_partition(STR): - sep = STR(" ") - s = STR("Here are some words. "*2) - s_partition = s.partition - for x in _RANGE_1000: - s_partition(sep) - - at bench('("Here are some words. "*2).rpartition(" ")', - "split 1 whitespace", 1000) -def whitespace_rpartition(STR): - sep = STR(" ") - s = STR("Here are some words. "*2) - s_rpartition = s.rpartition - for x in _RANGE_1000: - s_rpartition(sep) - -human_text = """\ -Python is a dynamic object-oriented programming language that can be -used for many kinds of software development. It offers strong support -for integration with other languages and tools, comes with extensive -standard libraries, and can be learned in a few days. Many Python -programmers report substantial productivity gains and feel the language -encourages the development of higher quality, more maintainable code. - -Python runs on Windows, Linux/Unix, Mac OS X, OS/2, Amiga, Palm -Handhelds, and Nokia mobile phones. Python has also been ported to the -Java and .NET virtual machines. - -Python is distributed under an OSI-approved open source license that -makes it free to use, even for commercial products. -"""*25 -human_text_bytes = bytes_from_str(human_text) -human_text_unicode = unicode_from_str(human_text) -def _get_human_text(STR): - if STR is UNICODE: - return human_text_unicode - if STR is BYTES: - return human_text_bytes - raise AssertionError - - at bench('human_text.split()', "split whitespace (huge)", 10) -def whitespace_split_huge(STR): - s = _get_human_text(STR) - s_split = s.split - for x in _RANGE_10: - s_split() - - at bench('human_text.rsplit()', "split whitespace (huge)", 10) -def whitespace_rsplit_huge(STR): - s = _get_human_text(STR) - s_rsplit = s.rsplit - for x in _RANGE_10: - s_rsplit() - - - - at bench('"this\\nis\\na\\ntest\\n".split("\\n")', "split newlines", 1000) -def newlines_split(STR): - s = STR("this\nis\na\ntest\n") - s_split = s.split - nl = STR("\n") - for x in _RANGE_1000: - s_split(nl) - - - at bench('"this\\nis\\na\\ntest\\n".rsplit("\\n")', "split newlines", 1000) -def newlines_rsplit(STR): - s = STR("this\nis\na\ntest\n") - s_rsplit = s.rsplit - nl = STR("\n") - for x in _RANGE_1000: - s_rsplit(nl) - - at bench('"this\\nis\\na\\ntest\\n".splitlines()', "split newlines", 1000) -def newlines_splitlines(STR): - s = STR("this\nis\na\ntest\n") - s_splitlines = s.splitlines - for x in _RANGE_1000: - s_splitlines() - -## split text with 2000 newlines - -def _make_2000_lines(): - import random - r = random.Random(100) - chars = list(map(chr, range(32, 128))) - i = 0 - while i < len(chars): - chars[i] = " " - i += r.randrange(9) - s = "".join(chars) - s = s*4 - words = [] - for i in range(2000): - start = r.randrange(96) - n = r.randint(5, 65) - words.append(s[start:start+n]) - return "\n".join(words)+"\n" - -_text_with_2000_lines = _make_2000_lines() -_text_with_2000_lines_bytes = bytes_from_str(_text_with_2000_lines) -_text_with_2000_lines_unicode = unicode_from_str(_text_with_2000_lines) -def _get_2000_lines(STR): - if STR is UNICODE: - return _text_with_2000_lines_unicode - if STR is BYTES: - return _text_with_2000_lines_bytes - raise AssertionError - - - at bench('"...text...".split("\\n")', "split 2000 newlines", 10) -def newlines_split_2000(STR): - s = _get_2000_lines(STR) - s_split = s.split - nl = STR("\n") - for x in _RANGE_10: - s_split(nl) - - at bench('"...text...".rsplit("\\n")', "split 2000 newlines", 10) -def newlines_rsplit_2000(STR): - s = _get_2000_lines(STR) - s_rsplit = s.rsplit - nl = STR("\n") - for x in _RANGE_10: - s_rsplit(nl) - - at bench('"...text...".splitlines()', "split 2000 newlines", 10) -def newlines_splitlines_2000(STR): - s = _get_2000_lines(STR) - s_splitlines = s.splitlines - for x in _RANGE_10: - s_splitlines() - - -## split text on "--" characters - at bench( - '"this--is--a--test--of--the--emergency--broadcast--system".split("--")', - "split on multicharacter separator (small)", 1000) -def split_multichar_sep_small(STR): - s = STR("this--is--a--test--of--the--emergency--broadcast--system") - s_split = s.split - pat = STR("--") - for x in _RANGE_1000: - s_split(pat) - at bench( - '"this--is--a--test--of--the--emergency--broadcast--system".rsplit("--")', - "split on multicharacter separator (small)", 1000) -def rsplit_multichar_sep_small(STR): - s = STR("this--is--a--test--of--the--emergency--broadcast--system") - s_rsplit = s.rsplit - pat = STR("--") - for x in _RANGE_1000: - s_rsplit(pat) - -## split dna text on "ACTAT" characters - at bench('dna.split("ACTAT")', - "split on multicharacter separator (dna)", 10) -def split_multichar_sep_dna(STR): - s = _get_dna(STR) - s_split = s.split - pat = STR("ACTAT") - for x in _RANGE_10: - s_split(pat) - - at bench('dna.rsplit("ACTAT")', - "split on multicharacter separator (dna)", 10) -def rsplit_multichar_sep_dna(STR): - s = _get_dna(STR) - s_rsplit = s.rsplit - pat = STR("ACTAT") - for x in _RANGE_10: - s_rsplit(pat) - - - -## split with limits - -GFF3_example = "\t".join([ - "I", "Genomic_canonical", "region", "357208", "396183", ".", "+", ".", - "ID=Sequence:R119;note=Clone R119%3B Genbank AF063007;Name=R119"]) - - at bench('GFF3_example.split("\\t")', "tab split", 1000) -def tab_split_no_limit(STR): - sep = STR("\t") - s = STR(GFF3_example) - s_split = s.split - for x in _RANGE_1000: - s_split(sep) - - at bench('GFF3_example.split("\\t", 8)', "tab split", 1000) -def tab_split_limit(STR): - sep = STR("\t") - s = STR(GFF3_example) - s_split = s.split - for x in _RANGE_1000: - s_split(sep, 8) - - at bench('GFF3_example.rsplit("\\t")', "tab split", 1000) -def tab_rsplit_no_limit(STR): - sep = STR("\t") - s = STR(GFF3_example) - s_rsplit = s.rsplit - for x in _RANGE_1000: - s_rsplit(sep) - - at bench('GFF3_example.rsplit("\\t", 8)', "tab split", 1000) -def tab_rsplit_limit(STR): - sep = STR("\t") - s = STR(GFF3_example) - s_rsplit = s.rsplit - for x in _RANGE_1000: - s_rsplit(sep, 8) - -#### Count characters - - at bench('...text.with.2000.newlines.count("\\n")', - "count newlines", 10) -def count_newlines(STR): - s = _get_2000_lines(STR) - s_count = s.count - nl = STR("\n") - for x in _RANGE_10: - s_count(nl) - -# Orchid sequences concatenated, from Biopython -_dna = """ -CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGTTGAGATCACATAATAATTGATCGGGTT -AATCTGGAGGATCTGTTTACTTTGGTCACCCATGAGCATTTGCTGTTGAAGTGACCTAGAATTGCCATCG -AGCCTCCTTGGGAGCTTTCTTGTTGGCGAGATCTAAACCCTTGCCCGGCGCAGTTTTGCTCCAAGTCGTT -TGACACATAATTGGTGAAGGGGGTGGCATCCTTCCCTGACCCTCCCCCAACTATTTTTTTAACAACTCTC -AGCAACGGAGACTCAGTCTTCGGCAAATGCGATAAATGGTGTGAATTGCAGAATCCCGTGCACCATCGAG -TCTTTGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCACGCCTGCCTGGGCATTGCGAGTCATAT -CTCTCCCTTAACGAGGCTGTCCATACATACTGTTCAGCCGGTGCGGATGTGAGTTTGGCCCCTTGTTCTT -TGGTACGGGGGGTCTAAGAGCTGCATGGGCTTTTGATGGTCCTAAATACGGCAAGAGGTGGACGAACTAT -GCTACAACAAAATTGTTGTGCAGAGGCCCCGGGTTGTCGTATTAGATGGGCCACCGTAATCTGAAGACCC -TTTTGAACCCCATTGGAGGCCCATCAACCCATGATCAGTTGATGGCCATTTGGTTGCGACCCCAGGTCAG -GTGAGCAACAGCTGTCGTAACAAGGTTTCCGTAGGGTGAACTGCGGAAGGATCATTGTTGAGATCACATA -ATAATTGATCGAGTTAATCTGGAGGATCTGTTTACTTGGGTCACCCATGGGCATTTGCTGTTGAAGTGAC -CTAGATTTGCCATCGAGCCTCCTTGGGAGCATCCTTGTTGGCGATATCTAAACCCTCAATTTTTCCCCCA -ATCAAATTACACAAAATTGGTGGAGGGGGTGGCATTCTTCCCTTACCCTCCCCCAAATATTTTTTTAACA -ACTCTCAGCAACGGATATCTCAGCTCTTGCATCGATGAAGAACCCACCGAAATGCGATAAATGGTGTGAA -TTGCAGAATCCCGTGAACCATCGAGTCTTTGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCACG -CCTGCCTGGGCATTGCGAGTCATATCTCTCCCTTAACGAGGCTGTCCATACATACTGTTCAGCCGGTGCG -GATGTGAGTTTGGCCCCTTGTTCTTTGGTACGGGGGGTCTAAGAGATGCATGGGCTTTTGATGGTCCTAA -ATACGGCAAGAGGTGGACGAACTATGCTACAACAAAATTGTTGTGCAAAGGCCCCGGGTTGTCGTATAAG -ATGGGCCACCGATATCTGAAGACCCTTTTGGACCCCATTGGAGCCCATCAACCCATGTCAGTTGATGGCC -ATTCGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGTTGAGATCACATAATAATTGATCGA -GTTAATCTGGAGGATCTGTTTACTTGGGTCACCCATGGGCATTTGCTGTTGAAGTGACCTAGATTTGCCA -TCGAGCCTCCTTGGGAGCTTTCTTGTTGGCGATATCTAAACCCTTGCCCGGCAGAGTTTTGGGAATCCCG -TGAACCATCGAGTCTTTGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCACGCCTGCCTGGGCAT -TGCGAGTCATATCTCTCCCTTAACGAGGCTGTCCATACACACCTGTTCAGCCGGTGCGGATGTGAGTTTG -GCCCCTTGTTCTTTGGTACGGGGGGTCTAAGAGCTGCATGGGCTTTTGATGGTCCTAAATACGGCAAGAG -GTGGACGAACTATGCTACAACAAAATTGTTGTGCAAAGGCCCCGGGTTGTCGTATTAGATGGGCCACCAT -AATCTGAAGACCCTTTTGAACCCCATTGGAGGCCCATCAACCCATGATCAGTTGATGGCCATTTGGTTGC -GACCCAGTCAGGTGAGGGTAGGTGAACCTGCGGAAGGATCATTGTTGAGATCACATAATAATTGATCGAG -TTAATCTGGAGGATCTGTTTACTTTGGTCACCCATGGGCATTTGCTGTTGAAGTGACCTAGATTTGCCAT -CGAGCCTCCTTGGGAGCTTTCTTGTTGGCGAGATCTAAACCCTTGCCCGGCGGAGTTTGGCGCCAAGTCA -TATGACACATAATTGGTGAAGGGGGTGGCATCCTGCCCTGACCCTCCCCAAATTATTTTTTTAACAACTC -TCAGCAACGGATATCTCGGCTCTTGCATCGATGAAGAACGCAGCGAAATGCGATAAATGGTGTGAATTGC -AGAATCCCGTGAACCATCGAGTCTTTGGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCACGCCT -GCCTGGGCATTGGGAATCATATCTCTCCCCTAACGAGGCTATCCAAACATACTGTTCATCCGGTGCGGAT -GTGAGTTTGGCCCCTTGTTCTTTGGTACCGGGGGTCTAAGAGCTGCATGGGCATTTGATGGTCCTCAAAA -CGGCAAGAGGTGGACGAACTATGCCACAACAAAATTGTTGTCCCAAGGCCCCGGGTTGTCGTATTAGATG -GGCCACCGTAACCTGAAGACCCTTTTGAACCCCATTGGAGGCCCATCAACCCATGATCAGTTGATGACCA -TTTGTTGCGACCCCAGTCAGCTGAGCAACCCGCTGAGTGGAAGGTCATTGCCGATATCACATAATAATTG -ATCGAGTTAATCTGGAGGATCTGTTTACTTGGTCACCCATGAGCATTTGCTGTTGAAGTGACCTAGATTT -GCCATCGAGCCTCCTTGGGAGTTTTCTTGTTGGCGAGATCTAAACCCTTGCCCGGCGGAGTTGTGCGCCA -AGTCATATGACACATAATTGGTGAAGGGGGTGGCATCCTGCCCTGACCCTCCCCAAATTATTTTTTTAAC -AACTCTCAGCAACGGATATCTCGGCTCTTGCATCGATGAAGAACGCAGCGAAATGCGATAAATGGTGTGA -ATTGCAGAATCCCGTGAACCATCGAGTCTTTGAACGCAAGTTGCGCCCGAGGCCATCAGGCCAAGGGCAC -GCCTGCCTGGGCATTGCGAGTCATATCTCTCCCTTAACGAGGCTGTCCATACATACTGTTCATCCGGTGC -GGATGTGAGTTTGGCCCCTTGTTCTTTGGTACGGGGGGTCTAAGAGCTGCATGGGCATTTGATGGTCCTC -AAAACGGCAAGAGGTGGACGAACTATGCTACAACCAAATTGTTGTCCCAAGGCCCCGGGTTGTCGTATTA -GATGGGCCACCGTAACCTGAAGACCCTTTTGAACCCCATTGGAGGCCCATCAACCCATGATCAGTTGATG -ACCATGTGTTGCGACCCCAGTCAGCTGAGCAACGCGCTGAGCGTAACAAGGTTTCCGTAGGTGGACCTCC -GGGAGGATCATTGTTGAGATCACATAATAATTGATCGAGGTAATCTGGAGGATCTGCATATTTTGGTCAC -""" -_dna = "".join(_dna.splitlines()) -_dna = _dna * 25 -_dna_bytes = bytes_from_str(_dna) -_dna_unicode = unicode_from_str(_dna) - -def _get_dna(STR): - if STR is UNICODE: - return _dna_unicode - if STR is BYTES: - return _dna_bytes - raise AssertionError - - at bench('dna.count("AACT")', "count AACT substrings in DNA example", 10) -def count_aact(STR): - seq = _get_dna(STR) - seq_count = seq.count - needle = STR("AACT") - for x in _RANGE_10: - seq_count(needle) - -##### startswith and endswith - - at bench('"Andrew".startswith("A")', 'startswith single character', 1000) -def startswith_single(STR): - s1 = STR("Andrew") - s2 = STR("A") - s1_startswith = s1.startswith - for x in _RANGE_1000: - s1_startswith(s2) - - at bench('"Andrew".startswith("Andrew")', 'startswith multiple characters', - 1000) -def startswith_multiple(STR): - s1 = STR("Andrew") - s2 = STR("Andrew") - s1_startswith = s1.startswith - for x in _RANGE_1000: - s1_startswith(s2) - - at bench('"Andrew".startswith("Anders")', - 'startswith multiple characters - not!', 1000) -def startswith_multiple_not(STR): - s1 = STR("Andrew") - s2 = STR("Anders") - s1_startswith = s1.startswith - for x in _RANGE_1000: - s1_startswith(s2) - - -# endswith - - at bench('"Andrew".endswith("w")', 'endswith single character', 1000) -def endswith_single(STR): - s1 = STR("Andrew") - s2 = STR("w") - s1_endswith = s1.endswith - for x in _RANGE_1000: - s1_endswith(s2) - - at bench('"Andrew".endswith("Andrew")', 'endswith multiple characters', 1000) -def endswith_multiple(STR): - s1 = STR("Andrew") - s2 = STR("Andrew") - s1_endswith = s1.endswith - for x in _RANGE_1000: - s1_endswith(s2) - - at bench('"Andrew".endswith("Anders")', - 'endswith multiple characters - not!', 1000) -def endswith_multiple_not(STR): - s1 = STR("Andrew") - s2 = STR("Anders") - s1_endswith = s1.endswith - for x in _RANGE_1000: - s1_endswith(s2) - -#### Strip - - at bench('"Hello!\\n".strip()', 'strip terminal newline', 1000) -def terminal_newline_strip_right(STR): - s = STR("Hello!\n") - s_strip = s.strip - for x in _RANGE_1000: - s_strip() - - at bench('"Hello!\\n".rstrip()', 'strip terminal newline', 1000) -def terminal_newline_rstrip(STR): - s = STR("Hello!\n") - s_rstrip = s.rstrip - for x in _RANGE_1000: - s_rstrip() - - at bench('"\\nHello!".strip()', 'strip terminal newline', 1000) -def terminal_newline_strip_left(STR): - s = STR("\nHello!") - s_strip = s.strip - for x in _RANGE_1000: - s_strip() - - at bench('"\\nHello!\\n".strip()', 'strip terminal newline', 1000) -def terminal_newline_strip_both(STR): - s = STR("\nHello!\n") - s_strip = s.strip - for x in _RANGE_1000: - s_strip() - - at bench('"\\nHello!".rstrip()', 'strip terminal newline', 1000) -def terminal_newline_lstrip(STR): - s = STR("\nHello!") - s_lstrip = s.lstrip - for x in _RANGE_1000: - s_lstrip() - - at bench('s="Hello!\\n"; s[:-1] if s[-1]=="\\n" else s', - 'strip terminal newline', 1000) -def terminal_newline_if_else(STR): - s = STR("Hello!\n") - NL = STR("\n") - for x in _RANGE_1000: - s[:-1] if (s[-1] == NL) else s - - -# Strip multiple spaces or tabs - - at bench('"Hello\\t \\t".strip()', 'strip terminal spaces and tabs', 1000) -def terminal_space_strip(STR): - s = STR("Hello\t \t!") - s_strip = s.strip - for x in _RANGE_1000: - s_strip() - - at bench('"Hello\\t \\t".rstrip()', 'strip terminal spaces and tabs', 1000) -def terminal_space_rstrip(STR): - s = STR("Hello!\t \t") - s_rstrip = s.rstrip - for x in _RANGE_1000: - s_rstrip() - - at bench('"\\t \\tHello".rstrip()', 'strip terminal spaces and tabs', 1000) -def terminal_space_lstrip(STR): - s = STR("\t \tHello!") - s_lstrip = s.lstrip - for x in _RANGE_1000: - s_lstrip() - - -#### replace - at bench('"This is a test".replace(" ", "\\t")', 'replace single character', - 1000) -def replace_single_character(STR): - s = STR("This is a test!") - from_str = STR(" ") - to_str = STR("\t") - s_replace = s.replace - for x in _RANGE_1000: - s_replace(from_str, to_str) - - at uses_re - at bench('re.sub(" ", "\\t", "This is a test"', 'replace single character', - 1000) -def replace_single_character_re(STR): - s = STR("This is a test!") - pat = re.compile(STR(" ")) - to_str = STR("\t") - pat_sub = pat.sub - for x in _RANGE_1000: - pat_sub(to_str, s) - - at bench('"...text.with.2000.lines...replace("\\n", " ")', - 'replace single character, big string', 10) -def replace_single_character_big(STR): - s = _get_2000_lines(STR) - from_str = STR("\n") - to_str = STR(" ") - s_replace = s.replace - for x in _RANGE_10: - s_replace(from_str, to_str) - - at uses_re - at bench('re.sub("\\n", " ", "...text.with.2000.lines...")', - 'replace single character, big string', 10) -def replace_single_character_big_re(STR): - s = _get_2000_lines(STR) - pat = re.compile(STR("\n")) - to_str = STR(" ") - pat_sub = pat.sub - for x in _RANGE_10: - pat_sub(to_str, s) - - - at bench('dna.replace("ATC", "ATT")', - 'replace multiple characters, dna', 10) -def replace_multiple_characters_dna(STR): - seq = _get_dna(STR) - from_str = STR("ATC") - to_str = STR("ATT") - seq_replace = seq.replace - for x in _RANGE_10: - seq_replace(from_str, to_str) - -# This increases the character count - at bench('"...text.with.2000.newlines...replace("\\n", "\\r\\n")', - 'replace and expand multiple characters, big string', 10) -def replace_multiple_character_big(STR): - s = _get_2000_lines(STR) - from_str = STR("\n") - to_str = STR("\r\n") - s_replace = s.replace - for x in _RANGE_10: - s_replace(from_str, to_str) - - -# This decreases the character count - at bench('"When shall we three meet again?".replace("ee", "")', - 'replace/remove multiple characters', 1000) -def replace_multiple_character_remove(STR): - s = STR("When shall we three meet again?") - from_str = STR("ee") - to_str = STR("") - s_replace = s.replace - for x in _RANGE_1000: - s_replace(from_str, to_str) - - -big_s = "A" + ("Z"*128*1024) -big_s_bytes = bytes_from_str(big_s) -big_s_unicode = unicode_from_str(big_s) -def _get_big_s(STR): - if STR is UNICODE: return big_s_unicode - if STR is BYTES: return big_s_bytes - raise AssertionError - -# The older replace implementation counted all matches in -# the string even when it only neeed to make one replacement. - at bench('("A" + ("Z"*128*1024)).replace("A", "BB", 1)', - 'quick replace single character match', 10) -def quick_replace_single_match(STR): - s = _get_big_s(STR) - from_str = STR("A") - to_str = STR("BB") - s_replace = s.replace - for x in _RANGE_10: - s_replace(from_str, to_str, 1) - - at bench('("A" + ("Z"*128*1024)).replace("AZZ", "BBZZ", 1)', - 'quick replace multiple character match', 10) -def quick_replace_multiple_match(STR): - s = _get_big_s(STR) - from_str = STR("AZZ") - to_str = STR("BBZZ") - s_replace = s.replace - for x in _RANGE_10: - s_replace(from_str, to_str, 1) - - -#### - -# CCP does a lot of this, for internationalisation of ingame messages. -_format = "The %(thing)s is %(place)s the %(location)s." -_format_dict = { "thing":"THING", "place":"PLACE", "location":"LOCATION", } -_format_bytes = bytes_from_str(_format) -_format_unicode = unicode_from_str(_format) -_format_dict_bytes = dict((bytes_from_str(k), bytes_from_str(v)) for (k,v) in _format_dict.items()) -_format_dict_unicode = dict((unicode_from_str(k), unicode_from_str(v)) for (k,v) in _format_dict.items()) - -def _get_format(STR): - if STR is UNICODE: - return _format_unicode - if STR is BYTES: - if sys.version_info >= (3,): - raise UnsupportedType - return _format_bytes - raise AssertionError - -def _get_format_dict(STR): - if STR is UNICODE: - return _format_dict_unicode - if STR is BYTES: - if sys.version_info >= (3,): - raise UnsupportedType - return _format_dict_bytes - raise AssertionError - -# Formatting. - at bench('"The %(k1)s is %(k2)s the %(k3)s."%{"k1":"x","k2":"y","k3":"z",}', - 'formatting a string type with a dict', 1000) -def format_with_dict(STR): - s = _get_format(STR) - d = _get_format_dict(STR) - for x in _RANGE_1000: - s % d - - -#### Upper- and lower- case conversion - - at bench('("Where in the world is Carmen San Deigo?"*10).lower()', - "case conversion -- rare", 1000) -def lower_conversion_rare(STR): - s = STR("Where in the world is Carmen San Deigo?"*10) - s_lower = s.lower - for x in _RANGE_1000: - s_lower() - - at bench('("WHERE IN THE WORLD IS CARMEN SAN DEIGO?"*10).lower()', - "case conversion -- dense", 1000) -def lower_conversion_dense(STR): - s = STR("WHERE IN THE WORLD IS CARMEN SAN DEIGO?"*10) - s_lower = s.lower - for x in _RANGE_1000: - s_lower() - - - at bench('("wHERE IN THE WORLD IS cARMEN sAN dEIGO?"*10).upper()', - "case conversion -- rare", 1000) -def upper_conversion_rare(STR): - s = STR("Where in the world is Carmen San Deigo?"*10) - s_upper = s.upper - for x in _RANGE_1000: - s_upper() - - at bench('("where in the world is carmen san deigo?"*10).upper()', - "case conversion -- dense", 1000) -def upper_conversion_dense(STR): - s = STR("where in the world is carmen san deigo?"*10) - s_upper = s.upper - for x in _RANGE_1000: - s_upper() - - -# end of benchmarks - -################# - -class BenchTimer(timeit.Timer): - def best(self, repeat=1): - for i in range(1, 10): - number = 10**i - x = self.timeit(number) - if x > 0.02: - break - times = [x] - for i in range(1, repeat): - times.append(self.timeit(number)) - return min(times) / number - -def main(): - (options, test_names) = parser.parse_args() - if options.bytes_only and options.unicode_only: - raise SystemExit("Only one of --8-bit and --unicode are allowed") - - bench_functions = [] - for (k,v) in globals().items(): - if hasattr(v, "is_bench"): - if test_names: - for name in test_names: - if name in v.group: - break - else: - # Not selected, ignore - continue - if options.skip_re and hasattr(v, "uses_re"): - continue - - bench_functions.append( (v.group, k, v) ) - bench_functions.sort() - - p("bytes\tunicode") - p("(in ms)\t(in ms)\t%\tcomment") - - bytes_total = uni_total = 0.0 - - for title, group in itertools.groupby(bench_functions, - operator.itemgetter(0)): - # Flush buffer before each group - sys.stdout.flush() - p("="*10, title) - for (_, k, v) in group: - if hasattr(v, "is_bench"): - bytes_time = 0.0 - bytes_time_s = " - " - if not options.unicode_only: - try: - bytes_time = BenchTimer("__main__.%s(__main__.BYTES)" % (k,), - "import __main__").best(REPEAT) - bytes_time_s = "%.2f" % (1000 * bytes_time) - bytes_total += bytes_time - except UnsupportedType: - bytes_time_s = "N/A" - uni_time = 0.0 - uni_time_s = " - " - if not options.bytes_only: - try: - uni_time = BenchTimer("__main__.%s(__main__.UNICODE)" % (k,), - "import __main__").best(REPEAT) - uni_time_s = "%.2f" % (1000 * uni_time) - uni_total += uni_time - except UnsupportedType: - uni_time_s = "N/A" - try: - average = bytes_time/uni_time - except (TypeError, ZeroDivisionError): - average = 0.0 - p("%s\t%s\t%.1f\t%s (*%d)" % ( - bytes_time_s, uni_time_s, 100.*average, - v.comment, v.repeat_count)) - - if bytes_total == uni_total == 0.0: - p("That was zippy!") - else: - try: - ratio = bytes_total/uni_total - except ZeroDivisionError: - ratio = 0.0 - p("%.2f\t%.2f\t%.1f\t%s" % ( - 1000*bytes_total, 1000*uni_total, 100.*ratio, - "TOTAL")) - -if __name__ == "__main__": - main() - From python-checkins at python.org Mon Apr 9 20:32:44 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 09 Apr 2012 20:32:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Use_the_MPD=28=29_accessor_?= =?utf8?q?macro=2E?= Message-ID: http://hg.python.org/cpython/rev/435b21afc6fa changeset: 76182:435b21afc6fa user: Stefan Krah date: Mon Apr 09 19:20:46 2012 +0200 summary: Use the MPD() accessor macro. files: Modules/_decimal/_decimal.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -3745,9 +3745,9 @@ } static int -nm_nonzero(PyDecObject *v) +nm_nonzero(PyObject *v) { - return !mpd_iszero(v->dec); + return !mpd_iszero(MPD(v)); } static PyObject * -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 20:32:45 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 09 Apr 2012 20:32:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Speed_up_=5Fdecimal_by_30-4?= =?utf8?q?0=25_for_numerical_workloads_by_improving_the_cache?= Message-ID: http://hg.python.org/cpython/rev/02c70dcb29dc changeset: 76183:02c70dcb29dc user: Stefan Krah date: Mon Apr 09 20:24:57 2012 +0200 summary: Speed up _decimal by 30-40% for numerical workloads by improving the cache locality for regularly sized coefficients. files: Modules/_decimal/_decimal.c | 36 +++++++++++++----------- 1 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -55,9 +55,13 @@ #define BOUNDS_CHECK(x, MIN, MAX) x = (x < MIN || MAX < x) ? MAX : x +/* _Py_DEC_MINALLOC >= MPD_MINALLOC */ +#define _Py_DEC_MINALLOC 4 + typedef struct { PyObject_HEAD - mpd_t *dec; + mpd_t dec; + mpd_uint_t data[_Py_DEC_MINALLOC]; } PyDecObject; typedef struct { @@ -90,7 +94,7 @@ #define PyDec_Check(v) PyObject_TypeCheck(v, &PyDec_Type) #define PyDecSignalDict_Check(v) (Py_TYPE(v) == PyDecSignalDict_Type) #define PyDecContext_Check(v) PyObject_TypeCheck(v, &PyDecContext_Type) -#define MPD(v) (((PyDecObject *)v)->dec) +#define MPD(v) (&((PyDecObject *)v)->dec) #define SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags) #define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags) #define CTX(v) (&((PyDecContextObject *)v)->ctx) @@ -1789,35 +1793,33 @@ static PyObject * PyDecType_New(PyTypeObject *type) { - PyObject *dec; + PyDecObject *dec; if (type == &PyDec_Type) { - dec = (PyObject *)PyObject_New(PyDecObject, &PyDec_Type); + dec = PyObject_New(PyDecObject, &PyDec_Type); } else { - dec = type->tp_alloc(type, 0); + dec = (PyDecObject *)type->tp_alloc(type, 0); } if (dec == NULL) { return NULL; } - MPD(dec) = mpd_qnew(); - if (MPD(dec) == NULL) { - Py_DECREF(dec); - PyErr_NoMemory(); - return NULL; - } - - return dec; + MPD(dec)->flags = MPD_STATIC|MPD_STATIC_DATA; + MPD(dec)->exp = 0; + MPD(dec)->digits = 0; + MPD(dec)->len = 0; + MPD(dec)->alloc = _Py_DEC_MINALLOC; + MPD(dec)->data = dec->data; + + return (PyObject *)dec; } #define dec_alloc() PyDecType_New(&PyDec_Type) static void dec_dealloc(PyObject *dec) { - if (MPD(dec)) { - mpd_del(MPD(dec)); - } + mpd_del(MPD(dec)); Py_TYPE(dec)->tp_free(dec); } @@ -5342,7 +5344,7 @@ mpd_reallocfunc = PyMem_Realloc; mpd_callocfunc = mpd_callocfunc_em; mpd_free = PyMem_Free; - mpd_setminalloc(4); + mpd_setminalloc(_Py_DEC_MINALLOC); /* Init types */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 20:32:46 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 09 Apr 2012 20:32:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_=5Fdecimal_is_now_100x_fast?= =?utf8?q?er_than_the_Python_version_in_the_pi_benchmark=2E?= Message-ID: http://hg.python.org/cpython/rev/02ecb8261cd8 changeset: 76184:02ecb8261cd8 user: Stefan Krah date: Mon Apr 09 20:31:15 2012 +0200 summary: _decimal is now 100x faster than the Python version in the pi benchmark. files: Doc/whatsnew/3.3.rst | 4 ++-- Misc/NEWS | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -628,7 +628,7 @@ library for arbitrary precision correctly-rounded decimal floating point arithmetic. libmpdec conforms to IBM's General Decimal Arithmetic Specification. -Performance gains range from 10x for database applications to 80x for +Performance gains range from 10x for database applications to 100x for numerically intensive applications. These numbers are expected gains for standard precisions used in decimal floating point arithmetic. Since the precision is user configurable, the exact figures may vary. For example, @@ -640,7 +640,7 @@ +---------+-------------+--------------+-------------+ | | decimal.py | _decimal | speedup | +=========+=============+==============+=============+ - | pi | 42.75s | 0.58s | 74x | + | pi | 38.89s | 0.38s | 100x | +---------+-------------+--------------+-------------+ | telco | 172.19s | 5.68s | 30x | +---------+-------------+--------------+-------------+ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -147,7 +147,7 @@ - Issue #7652: Integrate the decimal floating point libmpdec library to speed up the decimal module. Performance gains of the new C implementation are - between 12x and 80x, depending on the application. + between 10x and 100x, depending on the application. - Issue #3573: IDLE hangs when passing invalid command line args (directory(ies) instead of file(s)) (Patch by Guilherme Polo) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 20:47:23 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 09 Apr 2012 20:47:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Corrected_comme?= =?utf8?q?nt_in_cookbook_example_script=2E?= Message-ID: http://hg.python.org/cpython/rev/0da6aa7bc90b changeset: 76185:0da6aa7bc90b branch: 3.2 parent: 76171:f8e7fcd581ff user: Vinay Sajip date: Mon Apr 09 19:46:24 2012 +0100 summary: Corrected comment in cookbook example script. files: Doc/howto/logging-cookbook.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1350,7 +1350,7 @@ A simple handler for logging events. It runs in the listener process and dispatches events to loggers based on the name in the received record, which then get dispatched, by the logging system, to the handlers - configured for those records. + configured for those loggers. """ def handle(self, record): logger = logging.getLogger(record.name) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 20:47:24 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 09 Apr 2012 20:47:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merged_comment_correction_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/e493ff03561f changeset: 76186:e493ff03561f parent: 76184:02ecb8261cd8 parent: 76185:0da6aa7bc90b user: Vinay Sajip date: Mon Apr 09 19:47:16 2012 +0100 summary: Merged comment correction from 3.2. files: Doc/howto/logging-cookbook.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1377,7 +1377,7 @@ A simple handler for logging events. It runs in the listener process and dispatches events to loggers based on the name in the received record, which then get dispatched, by the logging system, to the handlers - configured for those records. + configured for those loggers. """ def handle(self, record): logger = logging.getLogger(record.name) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:00 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Fix_long-standi?= =?utf8?q?ng_bugs_with_MANIFEST=2Ein_parsing_on_Windows_=28=236884=29=2E?= Message-ID: http://hg.python.org/cpython/rev/b5f0ce4ddf0c changeset: 76187:b5f0ce4ddf0c branch: 2.7 parent: 75837:48172fcea164 user: ?ric Araujo date: Sat Feb 25 16:13:53 2012 +0100 summary: Fix long-standing bugs with MANIFEST.in parsing on Windows (#6884). These regex changes fix a number of issues for distutils on Windows: - #6884: impossible to include a file starting with 'build' - #9691 and #14004: sdist includes too many files - #13193: test_filelist failures This commit replaces the incorrect changes done in 557a973709de, c566a3447ba1 and 3925081a7ca0 to fix #13193; we were too eager to fix the test failures and I did not study the code enough before greenlighting patches. This time we have unit tests from the problems reported by users to be sure we have the right fix. Thanks to Nadeem Vawda for his help. files: Lib/distutils/filelist.py | 20 +- Lib/distutils/tests/test_filelist.py | 111 +++++++++----- Lib/distutils/tests/test_sdist.py | 14 +- Misc/NEWS | 5 +- 4 files changed, 97 insertions(+), 53 deletions(-) diff --git a/Lib/distutils/filelist.py b/Lib/distutils/filelist.py --- a/Lib/distutils/filelist.py +++ b/Lib/distutils/filelist.py @@ -210,6 +210,7 @@ Return 1 if files are found. """ + # XXX docstring lying about what the special chars are? files_found = 0 pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) self.debug_print("include_pattern: applying regex r'%s'" % @@ -297,11 +298,14 @@ # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, # and by extension they shouldn't match such "special characters" under # any OS. So change all non-escaped dots in the RE to match any - # character except the special characters. - # XXX currently the "special characters" are just slash -- i.e. this is - # Unix-only. - pattern_re = re.sub(r'((? http://hg.python.org/cpython/rev/7bb96963d067 changeset: 76188:7bb96963d067 branch: 2.7 user: Benjamin Peterson date: Thu Mar 22 23:32:23 2012 -0400 summary: move news thing around files: Misc/NEWS | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,6 +1,17 @@ Python News +++++++++++ +What's New in Python 2.7.3 final? +================================= + +*Release date: 2012-XX-XX* + +Library +------- + +- Issue #6884: Fix long-standing bugs with MANIFEST.in parsing in distutils + on Windows. + What's New in Python 2.7.3 release candidate 2? =============================================== @@ -113,9 +124,6 @@ Library ------- -- Issue #6884: Fix long-standing bugs with MANIFEST.in parsing in distutils - on Windows. - - Issue #8033: sqlite3: Fix 64-bit integer handling in user functions on 32-bit architectures. Initial patch by Philippe Devalkeneer. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:02 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:02 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_fix_build_witho?= =?utf8?q?ut_Py=5FDEBUG_and_DNDEBUG_=28closes_=2314509=29?= Message-ID: http://hg.python.org/cpython/rev/a11a2bbd8241 changeset: 76189:a11a2bbd8241 branch: 2.7 user: Benjamin Peterson date: Mon Apr 09 14:53:07 2012 -0400 summary: fix build without Py_DEBUG and DNDEBUG (closes #14509) files: Objects/stringobject.c | 2 ++ Objects/unicodeobject.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Objects/stringobject.c b/Objects/stringobject.c --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -1262,7 +1262,9 @@ register unsigned char *p; register long x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (a->ob_shash != -1) return a->ob_shash; len = Py_SIZE(a); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -6538,7 +6538,9 @@ register Py_UNICODE *p; register long x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (self->hash != -1) return self->hash; len = PyUnicode_GET_SIZE(self); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:03 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:03 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_merge_2=2E7_release_branch?= Message-ID: http://hg.python.org/cpython/rev/943567e04d27 changeset: 76190:943567e04d27 branch: 2.7 parent: 76173:4298d6e79ecb parent: 76189:a11a2bbd8241 user: Benjamin Peterson date: Mon Apr 09 14:54:09 2012 -0400 summary: merge 2.7 release branch files: Objects/stringobject.c | 2 ++ Objects/unicodeobject.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Objects/stringobject.c b/Objects/stringobject.c --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -1262,7 +1262,9 @@ register unsigned char *p; register long x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (a->ob_shash != -1) return a->ob_shash; len = Py_SIZE(a); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -6538,7 +6538,9 @@ register Py_UNICODE *p; register long x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (self->hash != -1) return self->hash; len = PyUnicode_GET_SIZE(self); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:04 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E1=29=3A_fix_build_witho?= =?utf8?q?ut_Py=5FDEBUG_and_DNDEBUG_=28closes_=2314509=29?= Message-ID: http://hg.python.org/cpython/rev/64bb1d258322 changeset: 76191:64bb1d258322 branch: 3.1 parent: 76142:f1876c0a630a user: Benjamin Peterson date: Mon Apr 09 14:53:07 2012 -0400 summary: fix build without Py_DEBUG and DNDEBUG (closes #14509) files: Objects/bytesobject.c | 2 ++ Objects/unicodeobject.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -896,7 +896,9 @@ register unsigned char *p; register long x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (a->ob_shash != -1) return a->ob_shash; len = Py_SIZE(a); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7341,7 +7341,9 @@ Py_UNICODE *p; long x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (self->hash != -1) return self->hash; len = Py_SIZE(self); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:05 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:05 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4xIC0+IDMuMik6?= =?utf8?q?_merge_3=2E1_=28=2314509=29?= Message-ID: http://hg.python.org/cpython/rev/5168483316b5 changeset: 76192:5168483316b5 branch: 3.2 parent: 76171:f8e7fcd581ff parent: 76191:64bb1d258322 user: Benjamin Peterson date: Mon Apr 09 15:01:02 2012 -0400 summary: merge 3.1 (#14509) files: Objects/bytesobject.c | 2 ++ Objects/unicodeobject.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -875,7 +875,9 @@ register unsigned char *p; register Py_hash_t x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (a->ob_shash != -1) return a->ob_shash; len = Py_SIZE(a); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7673,7 +7673,9 @@ Py_UNICODE *p; Py_hash_t x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (self->hash != -1) return self->hash; len = Py_SIZE(self); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:05 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?b?OiBtZXJnZSAzLjIgKCMxNDUwOSk=?= Message-ID: http://hg.python.org/cpython/rev/c20f604a2da6 changeset: 76193:c20f604a2da6 parent: 76184:02ecb8261cd8 parent: 76192:5168483316b5 user: Benjamin Peterson date: Mon Apr 09 15:04:39 2012 -0400 summary: merge 3.2 (#14509) files: Objects/object.c | 2 ++ Objects/unicodeobject.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -763,7 +763,9 @@ We make the hash of the empty string be 0, rather than using (prefix ^ suffix), since this slightly obfuscates the hash secret */ +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (len == 0) { return 0; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -11335,7 +11335,9 @@ Py_ssize_t len; Py_uhash_t x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (_PyUnicode_HASH(self) != -1) return _PyUnicode_HASH(self); if (PyUnicode_READY(self) == -1) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:06 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/211aded9df41 changeset: 76194:211aded9df41 parent: 76193:c20f604a2da6 parent: 76186:e493ff03561f user: Benjamin Peterson date: Mon Apr 09 15:05:13 2012 -0400 summary: merge heads files: Doc/howto/logging-cookbook.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1377,7 +1377,7 @@ A simple handler for logging events. It runs in the listener process and dispatches events to loggers based on the name in the received record, which then get dispatched, by the logging system, to the handlers - configured for those records. + configured for those loggers. """ def handle(self, record): logger = logging.getLogger(record.name) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:07 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:07 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMik6?= =?utf8?q?_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/aa6f9ab45da8 changeset: 76195:aa6f9ab45da8 branch: 3.2 parent: 76192:5168483316b5 parent: 76185:0da6aa7bc90b user: Benjamin Peterson date: Mon Apr 09 15:05:23 2012 -0400 summary: merge heads files: Doc/howto/logging-cookbook.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1350,7 +1350,7 @@ A simple handler for logging events. It runs in the listener process and dispatches events to loggers based on the name in the received record, which then get dispatched, by the logging system, to the handlers - configured for those records. + configured for those loggers. """ def handle(self, record): logger = logging.getLogger(record.name) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:06:08 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 09 Apr 2012 21:06:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/bada51b0c408 changeset: 76196:bada51b0c408 parent: 76194:211aded9df41 parent: 76195:aa6f9ab45da8 user: Benjamin Peterson date: Mon Apr 09 15:05:47 2012 -0400 summary: merge 3.2 files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:33:29 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 09 Apr 2012 21:33:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Resize_the_coefficient_to_M?= =?utf8?q?PD=5FMINALLOC_also_if_the_requested_size_is_below?= Message-ID: http://hg.python.org/cpython/rev/170bdc5c798b changeset: 76197:170bdc5c798b parent: 76184:02ecb8261cd8 user: Stefan Krah date: Mon Apr 09 20:47:57 2012 +0200 summary: Resize the coefficient to MPD_MINALLOC also if the requested size is below MPD_MINALLOC. Previously the resize was skipped as a micro optimization. files: Modules/_decimal/libmpdec/mpdecimal.c | 36 ++++++++------ 1 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -480,17 +480,20 @@ { assert(!mpd_isconst_data(result)); /* illegal operation for a const */ assert(!mpd_isshared_data(result)); /* illegal operation for a shared */ - + assert(MPD_MINALLOC <= result->alloc); + + nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords; + if (nwords == result->alloc) { + return 1; + } if (mpd_isstatic_data(result)) { if (nwords > result->alloc) { return mpd_switch_to_dyn(result, nwords, status); } - } - else if (nwords != result->alloc && nwords >= MPD_MINALLOC) { - return mpd_realloc_dyn(result, nwords, status); - } - - return 1; + return 1; + } + + return mpd_realloc_dyn(result, nwords, status); } /* Same as mpd_qresize, but the complete coefficient (including the old @@ -500,20 +503,21 @@ { assert(!mpd_isconst_data(result)); /* illegal operation for a const */ assert(!mpd_isshared_data(result)); /* illegal operation for a shared */ - - if (mpd_isstatic_data(result)) { - if (nwords > result->alloc) { - return mpd_switch_to_dyn_zero(result, nwords, status); - } - } - else if (nwords != result->alloc && nwords >= MPD_MINALLOC) { - if (!mpd_realloc_dyn(result, nwords, status)) { + assert(MPD_MINALLOC <= result->alloc); + + nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords; + if (nwords != result->alloc) { + if (mpd_isstatic_data(result)) { + if (nwords > result->alloc) { + return mpd_switch_to_dyn_zero(result, nwords, status); + } + } + else if (!mpd_realloc_dyn(result, nwords, status)) { return 0; } } mpd_uint_zero(result->data, nwords); - return 1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:33:30 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 09 Apr 2012 21:33:30 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314520=3A_Add_=5F?= =?utf8?q?=5Fsizeof=5F=5F=28=29_method_to_the_Decimal_object=2E?= Message-ID: http://hg.python.org/cpython/rev/010aa5d955ac changeset: 76198:010aa5d955ac user: Stefan Krah date: Mon Apr 09 21:27:20 2012 +0200 summary: Issue #14520: Add __sizeof__() method to the Decimal object. files: Modules/_decimal/_decimal.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -4340,6 +4340,19 @@ return result; } +/* __sizeof__ */ +static PyObject * +dec_sizeof(PyObject *v, PyObject *dummy UNUSED) +{ + Py_ssize_t res; + + res = sizeof(PyDecObject); + if (mpd_isdynamic_data(MPD(v))) { + res += MPD(v)->alloc * sizeof(mpd_uint_t); + } + return PyLong_FromSsize_t(res); +} + /* __trunc__ */ static PyObject * dec_trunc(PyObject *self, PyObject *dummy UNUSED) @@ -4503,6 +4516,7 @@ { "__floor__", dec_floor, METH_NOARGS, NULL }, { "__trunc__", dec_trunc, METH_NOARGS, NULL }, { "__complex__", dec_complex, METH_NOARGS, NULL }, + { "__sizeof__", dec_sizeof, METH_NOARGS, NULL }, { NULL, NULL, 1 } }; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 9 21:33:31 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 09 Apr 2012 21:33:31 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?b?KTogTWVyZ2Uu?= Message-ID: http://hg.python.org/cpython/rev/f432d3884b30 changeset: 76199:f432d3884b30 parent: 76198:010aa5d955ac parent: 76196:bada51b0c408 user: Stefan Krah date: Mon Apr 09 21:31:06 2012 +0200 summary: Merge. files: Doc/howto/logging-cookbook.rst | 2 +- Objects/object.c | 2 ++ Objects/unicodeobject.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1377,7 +1377,7 @@ A simple handler for logging events. It runs in the listener process and dispatches events to loggers based on the name in the received record, which then get dispatched, by the logging system, to the handlers - configured for those records. + configured for those loggers. """ def handle(self, record): logger = logging.getLogger(record.name) diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -763,7 +763,9 @@ We make the hash of the empty string be 0, rather than using (prefix ^ suffix), since this slightly obfuscates the hash secret */ +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (len == 0) { return 0; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -11335,7 +11335,9 @@ Py_ssize_t len; Py_uhash_t x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (_PyUnicode_HASH(self) != -1) return _PyUnicode_HASH(self); if (PyUnicode_READY(self) == -1) -- Repository URL: http://hg.python.org/cpython From jimjjewett at gmail.com Mon Apr 9 22:44:58 2012 From: jimjjewett at gmail.com (Jim Jewett) Date: Mon, 9 Apr 2012 16:44:58 -0400 Subject: [Python-checkins] Who are the decimal volunteers? Re: cpython: Resize the coefficient to MPD_MINALLOC also if the requested size is below Message-ID: I remember that one of the concerns with cdecimal was whether it could be maintained by anyone except Stefan (and a few people who were already overcommitted). If anyone (including absolute newbies) wants to step up, now would be a good time to get involved. A few starter questions, whose answer it would be good to document: Why is there any need for MPD_MINALLOC at all for (immutable) numbers? I suspect that will involve fleshing out some of the memory management issues around dynamic decimals, as touched on here: http://www.bytereef.org/mpdecimal/doc/libmpdec/memory.html#static-and-dynamic-decimals On Mon, Apr 9, 2012 at 3:33 PM, stefan.krah wrote: > http://hg.python.org/cpython/rev/170bdc5c798b > changeset: ? 76197:170bdc5c798b > parent: ? ? ?76184:02ecb8261cd8 > user: ? ? ? ?Stefan Krah > date: ? ? ? ?Mon Apr 09 20:47:57 2012 +0200 > summary: > ?Resize the coefficient to MPD_MINALLOC also if the requested size is below > MPD_MINALLOC. Previously the resize was skipped as a micro optimization. > > files: > ?Modules/_decimal/libmpdec/mpdecimal.c | ?36 ++++++++------ > ?1 files changed, 20 insertions(+), 16 deletions(-) > > > diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c > --- a/Modules/_decimal/libmpdec/mpdecimal.c > +++ b/Modules/_decimal/libmpdec/mpdecimal.c > @@ -480,17 +480,20 @@ > ?{ > ? ? assert(!mpd_isconst_data(result)); /* illegal operation for a const */ > ? ? assert(!mpd_isshared_data(result)); /* illegal operation for a shared */ > - > + ? ?assert(MPD_MINALLOC <= result->alloc); > + > + ? ?nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords; > + ? ?if (nwords == result->alloc) { > + ? ? ? ?return 1; > + ? ?} > ? ? if (mpd_isstatic_data(result)) { > ? ? ? ? if (nwords > result->alloc) { > ? ? ? ? ? ? return mpd_switch_to_dyn(result, nwords, status); > ? ? ? ? } > - ? ?} > - ? ?else if (nwords != result->alloc && nwords >= MPD_MINALLOC) { > - ? ? ? ?return mpd_realloc_dyn(result, nwords, status); > - ? ?} > - > - ? ?return 1; > + ? ? ? ?return 1; > + ? ?} > + > + ? ?return mpd_realloc_dyn(result, nwords, status); > ?} > > ?/* Same as mpd_qresize, but the complete coefficient (including the old > @@ -500,20 +503,21 @@ > ?{ > ? ? assert(!mpd_isconst_data(result)); /* illegal operation for a const */ > ? ? assert(!mpd_isshared_data(result)); /* illegal operation for a shared */ > - > - ? ?if (mpd_isstatic_data(result)) { > - ? ? ? ?if (nwords > result->alloc) { > - ? ? ? ? ? ?return mpd_switch_to_dyn_zero(result, nwords, status); > - ? ? ? ?} > - ? ?} > - ? ?else if (nwords != result->alloc && nwords >= MPD_MINALLOC) { > - ? ? ? ?if (!mpd_realloc_dyn(result, nwords, status)) { > + ? ?assert(MPD_MINALLOC <= result->alloc); > + > + ? ?nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords; > + ? ?if (nwords != result->alloc) { > + ? ? ? ?if (mpd_isstatic_data(result)) { > + ? ? ? ? ? ?if (nwords > result->alloc) { > + ? ? ? ? ? ? ? ?return mpd_switch_to_dyn_zero(result, nwords, status); > + ? ? ? ? ? ?} > + ? ? ? ?} > + ? ? ? ?else if (!mpd_realloc_dyn(result, nwords, status)) { > ? ? ? ? ? ? return 0; > ? ? ? ? } > ? ? } > > ? ? mpd_uint_zero(result->data, nwords); > - > ? ? return 1; > ?} > > > -- > Repository URL: http://hg.python.org/cpython > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From python-checkins at python.org Tue Apr 10 01:06:16 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 10 Apr 2012 01:06:16 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogYnVtcCB0byAyLjcu?= =?utf8?q?3_final?= Message-ID: http://hg.python.org/cpython/rev/70274d53c1dd changeset: 76200:70274d53c1dd branch: 2.7 tag: v2.7.3 parent: 76189:a11a2bbd8241 user: Benjamin Peterson date: Mon Apr 09 19:04:04 2012 -0400 summary: bump to 2.7.3 final files: Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 2 +- Misc/RPM/python-2.7.spec | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,11 +23,11 @@ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 7 #define PY_MICRO_VERSION 3 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.7.3rc2" +#define PY_VERSION "2.7.3" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "2.7.3rc2" +__version__ = "2.7.3" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "2.7.3rc2" +IDLE_VERSION = "2.7.3" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -4,7 +4,7 @@ What's New in Python 2.7.3 final? ================================= -*Release date: 2012-XX-XX* +*Release date: 2012-04-09* Library ------- diff --git a/Misc/RPM/python-2.7.spec b/Misc/RPM/python-2.7.spec --- a/Misc/RPM/python-2.7.spec +++ b/Misc/RPM/python-2.7.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 2.7.3rc2 +%define version 2.7.3 %define libvers 2.7 #--end constants-- %define release 1pydotorg -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 01:06:17 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 10 Apr 2012 01:06:17 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Added_tag_v2=2E?= =?utf8?q?7=2E3_for_changeset_70274d53c1dd?= Message-ID: http://hg.python.org/cpython/rev/a4b57bf19747 changeset: 76201:a4b57bf19747 branch: 2.7 user: Benjamin Peterson date: Mon Apr 09 19:04:12 2012 -0400 summary: Added tag v2.7.3 for changeset 70274d53c1dd files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -152,3 +152,4 @@ 8527427914a29d895bcb30be76a465143993a793 v2.7.2 b2c6aff96e1251a4f03cf866e7e75fb8232869f2 v2.7.3rc1 d46c1973d3c407ecaa6a8ee16d3fad3ef506b51f v2.7.3rc2 +70274d53c1ddc60c5f9a2b8a422a49884021447c v2.7.3 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 01:06:18 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 10 Apr 2012 01:06:18 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_merge_2=2E7=2E3_release_branch?= Message-ID: http://hg.python.org/cpython/rev/9649871ef35b changeset: 76202:9649871ef35b branch: 2.7 parent: 76190:943567e04d27 parent: 76201:a4b57bf19747 user: Benjamin Peterson date: Mon Apr 09 19:05:58 2012 -0400 summary: merge 2.7.3 release branch files: .hgtags | 1 + Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/RPM/python-2.7.spec | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -154,3 +154,4 @@ 8527427914a29d895bcb30be76a465143993a793 v2.7.2 b2c6aff96e1251a4f03cf866e7e75fb8232869f2 v2.7.3rc1 d46c1973d3c407ecaa6a8ee16d3fad3ef506b51f v2.7.3rc2 +70274d53c1ddc60c5f9a2b8a422a49884021447c v2.7.3 diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,11 +23,11 @@ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 7 #define PY_MICRO_VERSION 3 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.7.3rc2" +#define PY_VERSION "2.7.3" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "2.7.3rc2" +__version__ = "2.7.3" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "2.7.3rc2" +IDLE_VERSION = "2.7.3" diff --git a/Misc/RPM/python-2.7.spec b/Misc/RPM/python-2.7.spec --- a/Misc/RPM/python-2.7.spec +++ b/Misc/RPM/python-2.7.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 2.7.3rc2 +%define version 2.7.3 %define libvers 2.7 #--end constants-- %define release 1pydotorg -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Apr 10 05:36:24 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 10 Apr 2012 05:36:24 +0200 Subject: [Python-checkins] Daily reference leaks (f432d3884b30): sum=0 Message-ID: results for f432d3884b30 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogDVLlZ2', '-x'] From python-checkins at python.org Tue Apr 10 13:52:12 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 13:52:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_minor_=2Erst_fi?= =?utf8?q?x?= Message-ID: http://hg.python.org/cpython/rev/35d95a36afbb changeset: 76203:35d95a36afbb branch: 2.7 user: Senthil Kumaran date: Tue Apr 10 19:50:08 2012 +0800 summary: minor .rst fix files: Doc/library/imp.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -65,7 +65,7 @@ path and the last item in the *description* tuple is :const:`PKG_DIRECTORY`. This function does not handle hierarchical module names (names containing - dots). In order to find *P*.*M*, that is, submodule *M* of package *P*, use + dots). In order to find *P.M*, that is, submodule *M* of package *P*, use :func:`find_module` and :func:`load_module` to find and load package *P*, and then use :func:`find_module` with the *path* argument set to ``P.__path__``. When *P* itself has a dotted name, apply this recipe recursively. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 13:52:13 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 13:52:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_minor_=2Erst_fi?= =?utf8?q?x?= Message-ID: http://hg.python.org/cpython/rev/bbc4758bc908 changeset: 76204:bbc4758bc908 branch: 3.2 parent: 76195:aa6f9ab45da8 user: Senthil Kumaran date: Tue Apr 10 19:51:00 2012 +0800 summary: minor .rst fix files: Doc/library/imp.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -64,7 +64,7 @@ path and the last item in the *description* tuple is :const:`PKG_DIRECTORY`. This function does not handle hierarchical module names (names containing - dots). In order to find *P*.*M*, that is, submodule *M* of package *P*, use + dots). In order to find *P.M*, that is, submodule *M* of package *P*, use :func:`find_module` and :func:`load_module` to find and load package *P*, and then use :func:`find_module` with the *path* argument set to ``P.__path__``. When *P* itself has a dotted name, apply this recipe recursively. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 13:52:14 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 13:52:14 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_-_minor_=2Erst_fix?= Message-ID: http://hg.python.org/cpython/rev/b6820ef06745 changeset: 76205:b6820ef06745 parent: 76199:f432d3884b30 parent: 76204:bbc4758bc908 user: Senthil Kumaran date: Tue Apr 10 19:51:58 2012 +0800 summary: merge - minor .rst fix files: Doc/library/imp.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -64,7 +64,7 @@ path and the last item in the *description* tuple is :const:`PKG_DIRECTORY`. This function does not handle hierarchical module names (names containing - dots). In order to find *P*.*M*, that is, submodule *M* of package *P*, use + dots). In order to find *P.M*, that is, submodule *M* of package *P*, use :func:`find_module` and :func:`load_module` to find and load package *P*, and then use :func:`find_module` with the *path* argument set to ``P.__path__``. When *P* itself has a dotted name, apply this recipe recursively. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 16:30:21 2012 From: python-checkins at python.org (stefan.krah) Date: Tue, 10 Apr 2012 16:30:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314478=3A_Cache_the?= =?utf8?q?_hash_of_a_Decimal_in_the_C_version=2E?= Message-ID: http://hg.python.org/cpython/rev/a012d5df2c73 changeset: 76206:a012d5df2c73 user: Stefan Krah date: Tue Apr 10 16:27:58 2012 +0200 summary: Issue #14478: Cache the hash of a Decimal in the C version. files: Modules/_decimal/_decimal.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -60,6 +60,7 @@ typedef struct { PyObject_HEAD + Py_hash_t hash; mpd_t dec; mpd_uint_t data[_Py_DEC_MINALLOC]; } PyDecObject; @@ -1805,6 +1806,8 @@ return NULL; } + dec->hash = -1; + MPD(dec)->flags = MPD_STATIC|MPD_STATIC_DATA; MPD(dec)->exp = 0; MPD(dec)->digits = 0; @@ -4210,7 +4213,7 @@ /* Always uses the module context */ static Py_hash_t -dec_hash(PyObject *v) +_dec_hash(PyDecObject *v) { #if defined(CONFIG_64) && _PyHASH_BITS == 61 /* 2**61 - 1 */ @@ -4323,6 +4326,16 @@ goto finish; } +static Py_hash_t +dec_hash(PyDecObject *self) +{ + if (self->hash == -1) { + self->hash = _dec_hash(self); + } + + return self->hash; +} + /* __reduce__ */ static PyObject * dec_reduce(PyObject *self, PyObject *dummy UNUSED) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 17:31:04 2012 From: python-checkins at python.org (barry.warsaw) Date: Tue, 10 Apr 2012 17:31:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E6=29=3A_update_docs?= Message-ID: http://hg.python.org/cpython/rev/02fc7606744d changeset: 76207:02fc7606744d branch: 2.6 parent: 75810:ecae43294a0e user: Barry Warsaw date: Tue Apr 10 10:56:26 2012 -0400 summary: update docs files: Lib/pydoc_topics.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/pydoc_topics.py b/Lib/pydoc_topics.py --- a/Lib/pydoc_topics.py +++ b/Lib/pydoc_topics.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Sat Mar 17 14:18:25 2012 +# Autogenerated by Sphinx on Tue Apr 10 10:39:11 2012 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\nto\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that ``__debug__`` and ``AssertionError``\nrefer to 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\n(command line option -O). The current code generator emits no code\nfor an assert statement when optimization is requested at compile\ntime. Note that it is unnecessary to include the source code for the\nexpression that failed in the error message; it will be displayed as\npart of the stack 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\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\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 is recursively defined as\nfollows.\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 object\n must be an iterable with the same number of items as there are\n targets in the target list, and the items are assigned, from left to\n right, to the corresponding targets. (This rule is relaxed as of\n Python 1.5; in earlier versions, the object had to be a tuple.\n Since strings are sequences, an assignment like ``a, b = "xy"`` is\n now legal as long as the string has the right length.)\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`` statement in the\n current code block: the name is bound to the object in the current\n local namespace.\n\n * Otherwise: the name is bound to the object in the current global\n namespace.\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 square\n brackets: The object must be an iterable with the same number of\n 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\n always set as an instance attribute, creating it if necessary.\n Thus, the two occurrences of ``a.x`` do not necessarily refer to the\n same attribute: if the RHS expression refers to a class attribute,\n the 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 a plain integer. If it is negative, the\n sequence\'s length is added to it. The resulting value must be a\n nonnegative integer less than the sequence\'s length, and the\n sequence is asked to assign the assigned object to its item with\n that index. If the index is out of range, ``IndexError`` is raised\n (assignment to a subscripted sequence cannot add new items to a\n 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* If the target is a slicing: The primary expression in the reference\n is evaluated. It should yield a mutable sequence object (such as a\n list). The assigned object should be a sequence object of the same\n type. Next, the lower and upper bound expressions are evaluated,\n insofar they are present; defaults are zero and the sequence\'s\n length. The bounds should evaluate to (small) integers. If either\n 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 object\n 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\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample ``a, b = b, a`` swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints ``[0, 2]``:\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print x\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 for 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\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\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 in front of the name, with leading underscores removed, and\na single underscore inserted in front of the class name. For example,\nthe identifier ``__spam`` occurring in a class named ``Ham`` will be\ntransformed to ``_Ham__spam``. This transformation is independent of\nthe syntactical context in which the identifier is used. If the\ntransformed name is extremely long (longer than 255 characters),\nimplementation defined truncation may happen. If the class name\nconsists only of underscores, no transformation is done.\n', -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 17:31:07 2012 From: python-checkins at python.org (barry.warsaw) Date: Tue, 10 Apr 2012 17:31:07 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi42KTogQnVtcCB0byAyLjYu?= =?utf8?q?8?= Message-ID: http://hg.python.org/cpython/rev/c9910fd022fc changeset: 76208:c9910fd022fc branch: 2.6 tag: v2.6.8 user: Barry Warsaw date: Tue Apr 10 10:59:35 2012 -0400 summary: Bump to 2.6.8 files: Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 8 ++++++++ Misc/RPM/python-2.6.spec | 2 +- README | 4 ++-- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,11 +23,11 @@ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 6 #define PY_MICRO_VERSION 8 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.6.8rc2" +#define PY_VERSION "2.6.8" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -22,5 +22,5 @@ # #--start constants-- -__version__ = "2.6.8rc2" +__version__ = "2.6.8" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "2.6.8rc2" +IDLE_VERSION = "2.6.8" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,14 @@ Python News +++++++++++ +What's New in Python 2.6.8? +=========================== + +*Release date: 2012-04-10* + +No changes since 2.6.8rc2. + + What's New in Python 2.6.8 rc 2? ================================ diff --git a/Misc/RPM/python-2.6.spec b/Misc/RPM/python-2.6.spec --- a/Misc/RPM/python-2.6.spec +++ b/Misc/RPM/python-2.6.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 2.6.8rc2 +%define version 2.6.8 %define libvers 2.6 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 2.6.8 rc 2 -================================= +This is Python version 2.6.8 +============================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 17:31:07 2012 From: python-checkins at python.org (barry.warsaw) Date: Tue, 10 Apr 2012 17:31:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E6=29=3A_Added_tag_v2=2E?= =?utf8?q?6=2E8_for_changeset_c9910fd022fc?= Message-ID: http://hg.python.org/cpython/rev/2eebf39a01ab changeset: 76209:2eebf39a01ab branch: 2.6 user: Barry Warsaw date: Tue Apr 10 11:18:47 2012 -0400 summary: Added tag v2.6.8 for changeset c9910fd022fc files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -139,3 +139,4 @@ 9f8771e0905277f8b3c2799113a062fda4164995 v2.6.6 caab08cd2b3eb5a6f78479b2513b65d36c754f41 v2.6.8rc1 1d1b7b9fad48bd0dc60dc8a06cca4459ef273127 v2.6.8rc2 +c9910fd022fc842e5578e1bf5a30ba55a37239fc v2.6.8 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 17:31:08 2012 From: python-checkins at python.org (barry.warsaw) Date: Tue, 10 Apr 2012 17:31:08 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi42IC0+IDIuNyk6?= =?utf8?q?_Mostly_null_merge_from_2=2E6=3B_tag_added?= Message-ID: http://hg.python.org/cpython/rev/9b9675995e29 changeset: 76210:9b9675995e29 branch: 2.7 parent: 76203:35d95a36afbb parent: 76209:2eebf39a01ab user: Barry Warsaw date: Tue Apr 10 11:30:43 2012 -0400 summary: Mostly null merge from 2.6; tag added files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -139,6 +139,7 @@ 9f8771e0905277f8b3c2799113a062fda4164995 v2.6.6 caab08cd2b3eb5a6f78479b2513b65d36c754f41 v2.6.8rc1 1d1b7b9fad48bd0dc60dc8a06cca4459ef273127 v2.6.8rc2 +c9910fd022fc842e5578e1bf5a30ba55a37239fc v2.6.8 b4107eb00b4271fb73a9e1b736d4f23460950778 v2.7a1 adc85ebc7271cc22e24e816782bb2b8d7fa3a6b3 v2.7a2 4180557b7a9bb9dd5341a18af199f843f199e46e v2.7a3 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 18:03:05 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 10 Apr 2012 18:03:05 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_CLOCK=5FBOOTTIM?= =?utf8?q?E_and_FreeBSD_kern=2Etimecounter=2Ehardware_sysctl?= Message-ID: http://hg.python.org/peps/rev/94793b715d71 changeset: 4211:94793b715d71 user: Victor Stinner date: Tue Apr 10 13:58:42 2012 +0200 summary: PEP 418: Add CLOCK_BOOTTIME and FreeBSD kern.timecounter.hardware sysctl files: pep-0418.txt | 29 ++++++++++++++++++++++++++++- 1 files changed, 28 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -260,7 +260,9 @@ * TSC (Time Stamp Counter): Historically, the TSC increased with every internal processor clock cycle, but now the rate is usually constant (even if the processor changes frequency) and usually equals the maximum processor - frequency. The instructor RDTSC can be used to read this counter. + frequency. Multiple cores having different TSC values. Hibernation of system + will reset TSC value. The instructor RDTSC can be used to read this counter. + CPU frequency scaling for power saving. * ACPI PMTMR (power management timer): ACPI 24-bit timer with a frequency of 3.5 MHz (3,579,545 Hz). HPET can cause around 3 seconds of drift per day. * Cyclone: The Cyclone timer uses a 32-bit counter on IBM Extended @@ -788,6 +790,31 @@ `_: "overview of time and timers". +FreeBSD timers +-------------- + +The sysctl program can be used to change the timecounter. For example:: + + # sysctl kern.timecounter.hardware="ACPI-fast" + kern.timecounter.hardware: HPET -> ACPI-fast + + +Sleep, suspend and monotonic time +================================= + +Linux +----- + +On Linux, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW includes time the system +spends in sleep; but it does not include time spent in hibernation (ACPI S3 +mode). If the system clock jumps backward, CLOCK_MONOTONIC and +CLOCK_MONOTONIC_RAW are not affected. + +Linux 2.6.39 and glibc 2.14 introduces a new clock: CLOCK_BOOTTIME. +CLOCK_BOOTTIME is idential to CLOCK_MONOTONIC, except it also includes any time +spent in suspend. Read also `Waking systems from suspend +`_ (March, 2011). + Sleeping ======== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 10 19:44:56 2012 From: python-checkins at python.org (vinay.sajip) Date: Tue, 10 Apr 2012 19:44:56 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NTQx?= =?utf8?q?=3A_Added_test/sndhdrdata_to_Makefile=2Epre=2Ein_for_installatio?= =?utf8?q?n=2E?= Message-ID: http://hg.python.org/cpython/rev/b2242224fb7f changeset: 76211:b2242224fb7f branch: 3.2 parent: 76204:bbc4758bc908 user: Vinay Sajip date: Tue Apr 10 18:41:48 2012 +0100 summary: Issue #14541: Added test/sndhdrdata to Makefile.pre.in for installation. files: Makefile.pre.in | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -917,7 +917,8 @@ LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ tkinter/test/test_ttk site-packages test \ test/capath test/data \ - test/cjkencodings test/decimaltestdata test/xmltestdata test/subprocessdata \ + test/cjkencodings test/decimaltestdata test/xmltestdata \ + test/subprocessdata test/sndhdrdata \ test/tracedmodules test/encoded_modules \ concurrent concurrent/futures encodings \ email email/mime email/test email/test/data \ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 19:44:57 2012 From: python-checkins at python.org (vinay.sajip) Date: Tue, 10 Apr 2012 19:44:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314541=3A_Merged_addition_of_test/sndhdrdata_to_Make?= =?utf8?b?ZmlsZS5wcmUuaW4gZnJvbSAzLjIu?= Message-ID: http://hg.python.org/cpython/rev/54bc19fc5b46 changeset: 76212:54bc19fc5b46 parent: 76206:a012d5df2c73 parent: 76211:b2242224fb7f user: Vinay Sajip date: Tue Apr 10 18:44:41 2012 +0100 summary: Issue #14541: Merged addition of test/sndhdrdata to Makefile.pre.in from 3.2. files: Makefile.pre.in | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -952,7 +952,7 @@ tkinter/test/test_ttk site-packages test \ test/capath test/data \ test/cjkencodings test/decimaltestdata test/xmltestdata \ - test/subprocessdata \ + test/subprocessdata test/sndhdrdata \ test/tracedmodules test/encoded_modules \ collections concurrent concurrent/futures encodings \ email email/mime test/test_email test/test_email/data \ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 20:54:00 2012 From: python-checkins at python.org (barry.warsaw) Date: Tue, 10 Apr 2012 20:54:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E6=29=3A_Post_release_tw?= =?utf8?q?iddle=2E?= Message-ID: http://hg.python.org/cpython/rev/f130ce67387d changeset: 76213:f130ce67387d branch: 2.6 parent: 76209:2eebf39a01ab user: Barry Warsaw date: Tue Apr 10 14:50:39 2012 -0400 summary: Post release twiddle. 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 @@ -27,7 +27,7 @@ #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.6.8" +#define PY_VERSION "2.6.8+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ 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 2.6.9 rc 1? +================================ + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 2.6.8? =========================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 20:54:01 2012 From: python-checkins at python.org (barry.warsaw) Date: Tue, 10 Apr 2012 20:54:01 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi42IC0+IDIuNyk6?= =?utf8?q?_null_merge?= Message-ID: http://hg.python.org/cpython/rev/118294ea7d3a changeset: 76214:118294ea7d3a branch: 2.7 parent: 76210:9b9675995e29 parent: 76213:f130ce67387d user: Barry Warsaw date: Tue Apr 10 14:53:36 2012 -0400 summary: null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:02:35 2012 From: python-checkins at python.org (vinay.sajip) Date: Tue, 10 Apr 2012 21:02:35 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Updated_logging?= =?utf8?q?_reference_and_HOWTO=2E?= Message-ID: http://hg.python.org/cpython/rev/5a4c78fc416d changeset: 76215:5a4c78fc416d branch: 2.7 parent: 76210:9b9675995e29 user: Vinay Sajip date: Tue Apr 10 19:52:06 2012 +0100 summary: Updated logging reference and HOWTO. files: Doc/howto/logging.rst | 15 +++++++++++++++ Doc/library/logging.rst | 16 ++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -642,6 +642,21 @@ code approach, mainly separation of configuration and code and the ability of noncoders to easily modify the logging properties. +.. warning:: The :func:`fileConfig` function takes a default parameter, + ``disable_existing_loggers``, which defaults to ``True`` for reasons of + backward compatibility. This may or may not be what you want, since it + will cause any loggers existing before the :func:`fileConfig` call to + be disabled unless they (or an ancestor) are explicitly named in the + configuration. Please refer to the reference documentation for more + information, and specify ``False`` for this parameter if you wish. + + The dictionary passed to :func:`dictConfig` can also specify a Boolean + value with key ``disable_existing_loggers``, which if not specified + explicitly in the dictionary also defaults to being interpreted as + ``True``. This leads to the logger-disabling behaviour described above, + which may not be what you want - in which case, provide the key + explicitly with a value of ``False``. + .. currentmodule:: logging Note that the class names referenced in config files need to be either relative diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -51,9 +51,21 @@ Logger Objects -------------- -Loggers have the following attributes and methods. Note that Loggers are never +Loggers have the following attributes and methods. Note that Loggers are never instantiated directly, but always through the module-level function -``logging.getLogger(name)``. +``logging.getLogger(name)``. Multiple calls to :func:`getLogger` with the same +name will always return a reference to the same Logger object. + +The ``name`` is potentially a period-separated hierarchical value, like +``foo.bar.baz`` (though it could also be just plain ``foo``, for example). +Loggers that are further down in the hierarchical list are children of loggers +higher up in the list. For example, given a logger with a name of ``foo``, +loggers with names of ``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all +descendants of ``foo``. The logger name hierarchy is analogous to the Python +package hierarchy, and identical to it if you organise your loggers on a +per-module basis using the recommended construction +``logging.getLogger(__name__)``. That's because in a module, ``__name__`` +is the module's name in the Python package namespace. .. class:: Logger -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:02:36 2012 From: python-checkins at python.org (vinay.sajip) Date: Tue, 10 Apr 2012 21:02:36 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Updated_logging?= =?utf8?q?_reference_and_HOWTO=2E?= Message-ID: http://hg.python.org/cpython/rev/2f2a4fdaddf0 changeset: 76216:2f2a4fdaddf0 branch: 3.2 parent: 76211:b2242224fb7f user: Vinay Sajip date: Tue Apr 10 19:59:50 2012 +0100 summary: Updated logging reference and HOWTO. files: Doc/howto/logging.rst | 16 ++++++++++++++++ Doc/library/logging.rst | 17 +++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -651,6 +651,22 @@ code approach, mainly separation of configuration and code and the ability of noncoders to easily modify the logging properties. +.. warning:: The :func:`fileConfig` function takes a default parameter, + ``disable_existing_loggers``, which defaults to ``True`` for reasons of + backward compatibility. This may or may not be what you want, since it + will cause any loggers existing before the :func:`fileConfig` call to + be disabled unless they (or an ancestor) are explicitly named in the + configuration. Please refer to the reference documentation for more + information, and specify ``False`` for this parameter if you wish. + + The dictionary passed to :func:`dictConfig` can also specify a Boolean + value with key ``disable_existing_loggers``, which if not specified + explicitly in the dictionary also defaults to being interpreted as + ``True``. This leads to the logger-disabling behaviour described above, + which may not be what you want - in which case, provide the key + explicitly with a value of ``False``. + + .. currentmodule:: logging Note that the class names referenced in config files need to be either relative diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -49,9 +49,22 @@ Logger Objects -------------- -Loggers have the following attributes and methods. Note that Loggers are never +Loggers have the following attributes and methods. Note that Loggers are never instantiated directly, but always through the module-level function -``logging.getLogger(name)``. +``logging.getLogger(name)``. Multiple calls to :func:`getLogger` with the same +name will always return a reference to the same Logger object. + +The ``name`` is potentially a period-separated hierarchical value, like +``foo.bar.baz`` (though it could also be just plain ``foo``, for example). +Loggers that are further down in the hierarchical list are children of loggers +higher up in the list. For example, given a logger with a name of ``foo``, +loggers with names of ``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all +descendants of ``foo``. The logger name hierarchy is analogous to the Python +package hierarchy, and identical to it if you organise your loggers on a +per-module basis using the recommended construction +``logging.getLogger(__name__)``. That's because in a module, ``__name__`` +is the module's name in the Python package namespace. + .. class:: Logger -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:02:37 2012 From: python-checkins at python.org (vinay.sajip) Date: Tue, 10 Apr 2012 21:02:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merged_updates_to_logging_reference_and_HOWTO_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/29ae90b00054 changeset: 76217:29ae90b00054 parent: 76212:54bc19fc5b46 parent: 76216:2f2a4fdaddf0 user: Vinay Sajip date: Tue Apr 10 20:00:43 2012 +0100 summary: Merged updates to logging reference and HOWTO from 3.2. files: Doc/howto/logging.rst | 16 ++++++++++++++++ Doc/library/logging.rst | 17 +++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -651,6 +651,22 @@ code approach, mainly separation of configuration and code and the ability of noncoders to easily modify the logging properties. +.. warning:: The :func:`fileConfig` function takes a default parameter, + ``disable_existing_loggers``, which defaults to ``True`` for reasons of + backward compatibility. This may or may not be what you want, since it + will cause any loggers existing before the :func:`fileConfig` call to + be disabled unless they (or an ancestor) are explicitly named in the + configuration. Please refer to the reference documentation for more + information, and specify ``False`` for this parameter if you wish. + + The dictionary passed to :func:`dictConfig` can also specify a Boolean + value with key ``disable_existing_loggers``, which if not specified + explicitly in the dictionary also defaults to being interpreted as + ``True``. This leads to the logger-disabling behaviour described above, + which may not be what you want - in which case, provide the key + explicitly with a value of ``False``. + + .. currentmodule:: logging Note that the class names referenced in config files need to be either relative diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -49,9 +49,22 @@ Logger Objects -------------- -Loggers have the following attributes and methods. Note that Loggers are never +Loggers have the following attributes and methods. Note that Loggers are never instantiated directly, but always through the module-level function -``logging.getLogger(name)``. +``logging.getLogger(name)``. Multiple calls to :func:`getLogger` with the same +name will always return a reference to the same Logger object. + +The ``name`` is potentially a period-separated hierarchical value, like +``foo.bar.baz`` (though it could also be just plain ``foo``, for example). +Loggers that are further down in the hierarchical list are children of loggers +higher up in the list. For example, given a logger with a name of ``foo``, +loggers with names of ``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all +descendants of ``foo``. The logger name hierarchy is analogous to the Python +package hierarchy, and identical to it if you organise your loggers on a +per-module basis using the recommended construction +``logging.getLogger(__name__)``. That's because in a module, ``__name__`` +is the module's name in the Python package namespace. + .. class:: Logger -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:02:38 2012 From: python-checkins at python.org (vinay.sajip) Date: Tue, 10 Apr 2012 21:02:38 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_Merged_upstream_change=2E?= Message-ID: http://hg.python.org/cpython/rev/7bd335fe4cb6 changeset: 76218:7bd335fe4cb6 branch: 2.7 parent: 76215:5a4c78fc416d parent: 76214:118294ea7d3a user: Vinay Sajip date: Tue Apr 10 20:01:35 2012 +0100 summary: Merged upstream change. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:19:11 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 21:19:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A__fix_the_incorr?= =?utf8?q?ect_changes_made_for_PATH=5FINFO_value_-_Issue10484?= Message-ID: http://hg.python.org/cpython/rev/89eeaa18700f changeset: 76219:89eeaa18700f branch: 2.7 parent: 76214:118294ea7d3a user: Senthil Kumaran date: Wed Apr 11 03:07:57 2012 +0800 summary: fix the incorrect changes made for PATH_INFO value - Issue10484 files: Lib/CGIHTTPServer.py | 16 ++++++---------- Lib/test/test_httpservers.py | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Lib/CGIHTTPServer.py b/Lib/CGIHTTPServer.py --- a/Lib/CGIHTTPServer.py +++ b/Lib/CGIHTTPServer.py @@ -85,8 +85,11 @@ (and the next character is a '/' or the end of the string). """ splitpath = _url_collapse_path_split(self.path) - if splitpath[0] in self.cgi_directories: - self.cgi_info = splitpath + joined_path = '/'.join(splitpath) + dir_sep = joined_path.find('/', 1) + head, tail = joined_path[:dir_sep], joined_path[dir_sep+1:] + if head in self.cgi_directories: + self.cgi_info = head, tail return True return False @@ -323,14 +326,7 @@ # Filter out blank non trailing parts before consuming the '..'. path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] if path_parts: - # Special case for CGI's for PATH_INFO - if path.startswith('/cgi-bin') or path.startswith('/htbin'): - tail_part = [] - while path_parts[-1] not in ('cgi-bin','htbin'): - tail_part.insert(0,path_parts.pop()) - tail_part = "/".join(tail_part) - else: - tail_part = path_parts.pop() + tail_part = path_parts.pop() else: tail_part = '' head_parts = [] diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -419,6 +419,7 @@ BaseTestCase.tearDown(self) def test_url_collapse_path_split(self): + # verify tail is the last portion and head is the rest on proper urls test_vectors = { '': ('/', ''), '..': IndexError, @@ -429,7 +430,6 @@ '/.//': ('/', ''), 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - '/cgi-bin/file1.py/PATH-INFO': ('/cgi-bin', 'file1.py/PATH-INFO'), 'a': ('/', 'a'), '/a': ('/', 'a'), '//a': ('/', 'a'), -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:19:12 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 21:19:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_3=2E2-_fix_the_?= =?utf8?q?incorrect_changes_made_for_PATH=5FINFO_value_-_Issue10484?= Message-ID: http://hg.python.org/cpython/rev/827a4062b1d6 changeset: 76220:827a4062b1d6 branch: 3.2 parent: 76211:b2242224fb7f user: Senthil Kumaran date: Wed Apr 11 03:15:28 2012 +0800 summary: 3.2- fix the incorrect changes made for PATH_INFO value - Issue10484 files: Lib/http/server.py | 16 ++++++---------- Lib/test/test_httpservers.py | 1 - 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -850,14 +850,7 @@ # Filter out blank non trailing parts before consuming the '..'. path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] if path_parts: - # Special case for CGI's for PATH_INFO - if path.startswith('/cgi-bin') or path.startswith('/htbin'): - tail_part = [] - while path_parts[-1] not in ('cgi-bin','htbin'): - tail_part.insert(0,path_parts.pop()) - tail_part = "/".join(tail_part) - else: - tail_part = path_parts.pop() + tail_part = path_parts.pop() else: tail_part = '' head_parts = [] @@ -952,8 +945,11 @@ """ splitpath = _url_collapse_path_split(self.path) - if splitpath[0] in self.cgi_directories: - self.cgi_info = splitpath + joined_path = '/'.join(splitpath) + dir_sep = joined_path.find('/',1) + head, tail = joined_path[:dir_sep], joined_path[dir_sep+1:] + if head in self.cgi_directories: + self.cgi_info = head, tail return True return False diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -377,7 +377,6 @@ '/.//': ('/', ''), 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - '/cgi-bin/file1.py/PATH-INFO': ('/cgi-bin', 'file1.py/PATH-INFO'), 'a': ('/', 'a'), '/a': ('/', 'a'), '//a': ('/', 'a'), -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:19:13 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 21:19:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_-_fix_the_incorrect_changes_made_for_PATH=5FINFO_value?= =?utf8?q?_-_Issue10484?= Message-ID: http://hg.python.org/cpython/rev/8bcc5768bc05 changeset: 76221:8bcc5768bc05 parent: 76212:54bc19fc5b46 parent: 76220:827a4062b1d6 user: Senthil Kumaran date: Wed Apr 11 03:16:16 2012 +0800 summary: merge - fix the incorrect changes made for PATH_INFO value - Issue10484 files: Lib/http/server.py | 16 ++++++---------- Lib/test/test_httpservers.py | 1 - 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -865,14 +865,7 @@ # Filter out blank non trailing parts before consuming the '..'. path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] if path_parts: - # Special case for CGI's for PATH_INFO - if path.startswith('/cgi-bin') or path.startswith('/htbin'): - tail_part = [] - while path_parts[-1] not in ('cgi-bin','htbin'): - tail_part.insert(0,path_parts.pop()) - tail_part = "/".join(tail_part) - else: - tail_part = path_parts.pop() + tail_part = path_parts.pop() else: tail_part = '' head_parts = [] @@ -963,8 +956,11 @@ """ splitpath = _url_collapse_path_split(self.path) - if splitpath[0] in self.cgi_directories: - self.cgi_info = splitpath + joined_path = '/'.join(splitpath) + dir_sep = joined_path.find('/',1) + head, tail = joined_path[:dir_sep], joined_path[dir_sep+1:] + if head in self.cgi_directories: + self.cgi_info = head, tail return True return False diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -377,7 +377,6 @@ '/.//': ('/', ''), 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - '/cgi-bin/file1.py/PATH-INFO': ('/cgi-bin', 'file1.py/PATH-INFO'), 'a': ('/', 'a'), '/a': ('/', 'a'), '//a': ('/', 'a'), -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:19:15 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 21:19:15 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/64c26ac35b06 changeset: 76222:64c26ac35b06 parent: 76221:8bcc5768bc05 parent: 76217:29ae90b00054 user: Senthil Kumaran date: Wed Apr 11 03:17:44 2012 +0800 summary: merge heads files: Doc/howto/logging.rst | 16 ++++++++++++++++ Doc/library/logging.rst | 17 +++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -651,6 +651,22 @@ code approach, mainly separation of configuration and code and the ability of noncoders to easily modify the logging properties. +.. warning:: The :func:`fileConfig` function takes a default parameter, + ``disable_existing_loggers``, which defaults to ``True`` for reasons of + backward compatibility. This may or may not be what you want, since it + will cause any loggers existing before the :func:`fileConfig` call to + be disabled unless they (or an ancestor) are explicitly named in the + configuration. Please refer to the reference documentation for more + information, and specify ``False`` for this parameter if you wish. + + The dictionary passed to :func:`dictConfig` can also specify a Boolean + value with key ``disable_existing_loggers``, which if not specified + explicitly in the dictionary also defaults to being interpreted as + ``True``. This leads to the logger-disabling behaviour described above, + which may not be what you want - in which case, provide the key + explicitly with a value of ``False``. + + .. currentmodule:: logging Note that the class names referenced in config files need to be either relative diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -49,9 +49,22 @@ Logger Objects -------------- -Loggers have the following attributes and methods. Note that Loggers are never +Loggers have the following attributes and methods. Note that Loggers are never instantiated directly, but always through the module-level function -``logging.getLogger(name)``. +``logging.getLogger(name)``. Multiple calls to :func:`getLogger` with the same +name will always return a reference to the same Logger object. + +The ``name`` is potentially a period-separated hierarchical value, like +``foo.bar.baz`` (though it could also be just plain ``foo``, for example). +Loggers that are further down in the hierarchical list are children of loggers +higher up in the list. For example, given a logger with a name of ``foo``, +loggers with names of ``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all +descendants of ``foo``. The logger name hierarchy is analogous to the Python +package hierarchy, and identical to it if you organise your loggers on a +per-module basis using the recommended construction +``logging.getLogger(__name__)``. That's because in a module, ``__name__`` +is the module's name in the Python package namespace. + .. class:: Logger -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:19:16 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 21:19:16 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMik6?= =?utf8?q?_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/41e4be773044 changeset: 76223:41e4be773044 branch: 3.2 parent: 76220:827a4062b1d6 parent: 76216:2f2a4fdaddf0 user: Senthil Kumaran date: Wed Apr 11 03:18:25 2012 +0800 summary: merge heads files: Doc/howto/logging.rst | 16 ++++++++++++++++ Doc/library/logging.rst | 17 +++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -651,6 +651,22 @@ code approach, mainly separation of configuration and code and the ability of noncoders to easily modify the logging properties. +.. warning:: The :func:`fileConfig` function takes a default parameter, + ``disable_existing_loggers``, which defaults to ``True`` for reasons of + backward compatibility. This may or may not be what you want, since it + will cause any loggers existing before the :func:`fileConfig` call to + be disabled unless they (or an ancestor) are explicitly named in the + configuration. Please refer to the reference documentation for more + information, and specify ``False`` for this parameter if you wish. + + The dictionary passed to :func:`dictConfig` can also specify a Boolean + value with key ``disable_existing_loggers``, which if not specified + explicitly in the dictionary also defaults to being interpreted as + ``True``. This leads to the logger-disabling behaviour described above, + which may not be what you want - in which case, provide the key + explicitly with a value of ``False``. + + .. currentmodule:: logging Note that the class names referenced in config files need to be either relative diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -49,9 +49,22 @@ Logger Objects -------------- -Loggers have the following attributes and methods. Note that Loggers are never +Loggers have the following attributes and methods. Note that Loggers are never instantiated directly, but always through the module-level function -``logging.getLogger(name)``. +``logging.getLogger(name)``. Multiple calls to :func:`getLogger` with the same +name will always return a reference to the same Logger object. + +The ``name`` is potentially a period-separated hierarchical value, like +``foo.bar.baz`` (though it could also be just plain ``foo``, for example). +Loggers that are further down in the hierarchical list are children of loggers +higher up in the list. For example, given a logger with a name of ``foo``, +loggers with names of ``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all +descendants of ``foo``. The logger name hierarchy is analogous to the Python +package hierarchy, and identical to it if you organise your loggers on a +per-module basis using the recommended construction +``logging.getLogger(__name__)``. That's because in a module, ``__name__`` +is the module's name in the Python package namespace. + .. class:: Logger -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:19:17 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 21:19:17 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/65359495897b changeset: 76224:65359495897b branch: 2.7 parent: 76219:89eeaa18700f parent: 76218:7bd335fe4cb6 user: Senthil Kumaran date: Wed Apr 11 03:18:45 2012 +0800 summary: merge heads files: Doc/howto/logging.rst | 15 +++++++++++++++ Doc/library/logging.rst | 16 ++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -642,6 +642,21 @@ code approach, mainly separation of configuration and code and the ability of noncoders to easily modify the logging properties. +.. warning:: The :func:`fileConfig` function takes a default parameter, + ``disable_existing_loggers``, which defaults to ``True`` for reasons of + backward compatibility. This may or may not be what you want, since it + will cause any loggers existing before the :func:`fileConfig` call to + be disabled unless they (or an ancestor) are explicitly named in the + configuration. Please refer to the reference documentation for more + information, and specify ``False`` for this parameter if you wish. + + The dictionary passed to :func:`dictConfig` can also specify a Boolean + value with key ``disable_existing_loggers``, which if not specified + explicitly in the dictionary also defaults to being interpreted as + ``True``. This leads to the logger-disabling behaviour described above, + which may not be what you want - in which case, provide the key + explicitly with a value of ``False``. + .. currentmodule:: logging Note that the class names referenced in config files need to be either relative diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -51,9 +51,21 @@ Logger Objects -------------- -Loggers have the following attributes and methods. Note that Loggers are never +Loggers have the following attributes and methods. Note that Loggers are never instantiated directly, but always through the module-level function -``logging.getLogger(name)``. +``logging.getLogger(name)``. Multiple calls to :func:`getLogger` with the same +name will always return a reference to the same Logger object. + +The ``name`` is potentially a period-separated hierarchical value, like +``foo.bar.baz`` (though it could also be just plain ``foo``, for example). +Loggers that are further down in the hierarchical list are children of loggers +higher up in the list. For example, given a logger with a name of ``foo``, +loggers with names of ``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all +descendants of ``foo``. The logger name hierarchy is analogous to the Python +package hierarchy, and identical to it if you organise your loggers on a +per-module basis using the recommended construction +``logging.getLogger(__name__)``. That's because in a module, ``__name__`` +is the module's name in the Python package namespace. .. class:: Logger -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 21:23:21 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 10 Apr 2012 21:23:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A__Fix_closes_Iss?= =?utf8?q?ue14258__-_Clarify_the_re=2ELOCALE_and_re=2EUNICODE_flags_for_?= =?utf8?q?=5CS?= Message-ID: http://hg.python.org/cpython/rev/4d49a2415ced changeset: 76225:4d49a2415ced branch: 2.7 user: Senthil Kumaran date: Wed Apr 11 03:22:58 2012 +0800 summary: Fix closes Issue14258 - Clarify the re.LOCALE and re.UNICODE flags for \S class files: Doc/library/re.rst | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -353,20 +353,20 @@ character properties database. ``\s`` - When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, matches - any whitespace character; this is equivalent to the set ``[ \t\n\r\f\v]``. With - :const:`LOCALE`, it will match this set plus whatever characters are defined as - space for the current locale. If :const:`UNICODE` is set, this will match the - characters ``[ \t\n\r\f\v]`` plus whatever is classified as space in the Unicode - character properties database. + When the :const:`UNICODE` flag is not specified, it matches any whitespace + character, this is equivalent to the set ``[ \t\n\r\f\v]``. The + :const:`LOCALE` flag has no extra effect on matching of the space. + If :const:`UNICODE` is set, this will match the characters ``[ \t\n\r\f\v]`` + plus whatever is classified as space in the Unicode character properties + database. ``\S`` - When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, - matches any non-whitespace character; this is equivalent to the set ``[^ - \t\n\r\f\v]`` With :const:`LOCALE`, it will match the above set plus any - non-space character in the current locale. If :const:`UNICODE` is set, the - above set ``[^ \t\n\r\f\v]`` plus the characters not marked as space in the - Unicode character properties database. + When the :const:`UNICODE` flags is not specified, matches any non-whitespace + character; this is equivalent to the set ``[^ \t\n\r\f\v]`` The + :const:`LOCALE` flag has no extra effect on non-whitespace match. If + :const:`UNICODE` is set, then any character not marked as space in the + Unicode character properties database is matched. + ``\w`` When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, matches -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 22:57:04 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 10 Apr 2012 22:57:04 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzg3OTk6?= =?utf8?q?_Fix_and_improve_the_threading=2ECondition_documentation=2E?= Message-ID: http://hg.python.org/cpython/rev/2f51dca92883 changeset: 76226:2f51dca92883 branch: 3.2 parent: 76223:41e4be773044 user: Antoine Pitrou date: Tue Apr 10 22:24:05 2012 +0200 summary: Issue #8799: Fix and improve the threading.Condition documentation. files: Doc/library/threading.rst | 103 +++++++++++++------------ Misc/NEWS | 5 + 2 files changed, 59 insertions(+), 49 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -503,62 +503,73 @@ ----------------- A condition variable is always associated with some kind of lock; this can be -passed in or one will be created by default. (Passing one in is useful when -several condition variables must share the same lock.) +passed in or one will be created by default. Passing one in is useful when +several condition variables must share the same lock. The lock is part of +the condition object: you don't have to track it separately. -A condition variable has :meth:`acquire` and :meth:`release` methods that call -the corresponding methods of the associated lock. It also has a :meth:`wait` -method, and :meth:`notify` and :meth:`notify_all` methods. These three must only -be called when the calling thread has acquired the lock, otherwise a -:exc:`RuntimeError` is raised. +A condition variable obeys the :term:`context manager` protocol: using the +``with`` statement acquires the associated lock for the duration of the +enclosed block. The :meth:`~Condition.acquire` and :meth:`~Condition.release` +methods also call the corresponding methods of the associated lock. -The :meth:`wait` method releases the lock, and then blocks until it is awakened -by a :meth:`notify` or :meth:`notify_all` call for the same condition variable in -another thread. Once awakened, it re-acquires the lock and returns. It is also -possible to specify a timeout. +Other methods must be called with the associated lock held. The +:meth:`~Condition.wait` method releases the lock, and then blocks until +another thread awakens it by calling :meth:`~Condition.notify` or +:meth:`~Condition.notify_all`. Once awakened, :meth:`~Condition.wait` +re-acquires the lock and returns. It is also possible to specify a timeout. -The :meth:`notify` method wakes up one of the threads waiting for the condition -variable, if any are waiting. The :meth:`notify_all` method wakes up all threads -waiting for the condition variable. +The :meth:`~Condition.notify` method wakes up one of the threads waiting for +the condition variable, if any are waiting. The :meth:`~Condition.notify_all` +method wakes up all threads waiting for the condition variable. -Note: the :meth:`notify` and :meth:`notify_all` methods don't release the lock; -this means that the thread or threads awakened will not return from their -:meth:`wait` call immediately, but only when the thread that called -:meth:`notify` or :meth:`notify_all` finally relinquishes ownership of the lock. +Note: the :meth:`~Condition.notify` and :meth:`~Condition.notify_all` methods +don't release the lock; this means that the thread or threads awakened will +not return from their :meth:`~Condition.wait` call immediately, but only when +the thread that called :meth:`~Condition.notify` or :meth:`~Condition.notify_all` +finally relinquishes ownership of the lock. -Tip: the typical programming style using condition variables uses the lock to + +Usage +^^^^^ + +The typical programming style using condition variables uses the lock to synchronize access to some shared state; threads that are interested in a -particular change of state call :meth:`wait` repeatedly until they see the -desired state, while threads that modify the state call :meth:`notify` or -:meth:`notify_all` when they change the state in such a way that it could -possibly be a desired state for one of the waiters. For example, the following -code is a generic producer-consumer situation with unlimited buffer capacity:: +particular change of state call :meth:`~Condition.wait` repeatedly until they +see the desired state, while threads that modify the state call +:meth:`~Condition.notify` or :meth:`~Condition.notify_all` when they change +the state in such a way that it could possibly be a desired state for one +of the waiters. For example, the following code is a generic +producer-consumer situation with unlimited buffer capacity:: # Consume one item - cv.acquire() - while not an_item_is_available(): - cv.wait() - get_an_available_item() - cv.release() + with cv: + while not an_item_is_available(): + cv.wait() + get_an_available_item() # Produce one item - cv.acquire() - make_an_item_available() - cv.notify() - cv.release() + with cv: + make_an_item_available() -To choose between :meth:`notify` and :meth:`notify_all`, consider whether one -state change can be interesting for only one or several waiting threads. E.g. -in a typical producer-consumer situation, adding one item to the buffer only -needs to wake up one consumer thread. +The ``while`` loop checking for the application's condition is necessary +because :meth:`~Condition.wait` can return after an arbitrary long time, +and other threads may have exhausted the available items in between. This +is inherent to multi-threaded programming. The :meth:`~Condition.wait_for` +method can be used to automate the condition checking:: -Note: Condition variables can be, depending on the implementation, subject -to both spurious wakeups (when :meth:`wait` returns without a :meth:`notify` -call) and stolen wakeups (when another thread acquires the lock before the -awoken thread.) For this reason, it is always necessary to verify the state -the thread is waiting for when :meth:`wait` returns and optionally repeat -the call as often as necessary. + # Consume an item + with cv: + cv.wait_for(an_item_is_available) + get_an_available_item() +To choose between :meth:`~Condition.notify` and :meth:`~Condition.notify_all`, +consider whether one state change can be interesting for only one or several +waiting threads. E.g. in a typical producer-consumer situation, adding one +item to the buffer only needs to wake up one consumer thread. + + +Interface +^^^^^^^^^ .. class:: Condition(lock=None) @@ -626,12 +637,6 @@ held when called and is re-aquired on return. The predicate is evaluated with the lock held. - Using this method, the consumer example above can be written thus:: - - with cv: - cv.wait_for(an_item_is_available) - get_an_available_item() - .. versionadded:: 3.2 .. method:: notify(n=1) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -138,6 +138,11 @@ - Issue #14359: Only use O_CLOEXEC in _posixmodule.c if it is defined. Based on patch from Herv? Coatanhay. +Documentation +------------- + +- Issue #8799: Fix and improve the threading.Condition documentation. + What's New in Python 3.2.3 release candidate 2? =============================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 22:57:05 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 10 Apr 2012 22:57:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Fix_some_markup?= =?utf8?q?_in_the_threading_docs=2E?= Message-ID: http://hg.python.org/cpython/rev/c4cf1b886d6b changeset: 76227:c4cf1b886d6b branch: 3.2 user: Antoine Pitrou date: Tue Apr 10 22:35:53 2012 +0200 summary: Fix some markup in the threading docs. files: Doc/library/threading.rst | 146 +++++++++++++------------ 1 files changed, 77 insertions(+), 69 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -218,30 +218,31 @@ This class represents an activity that is run in a separate thread of control. There are two ways to specify the activity: by passing a callable object to the -constructor, or by overriding the :meth:`run` method in a subclass. No other -methods (except for the constructor) should be overridden in a subclass. In -other words, *only* override the :meth:`__init__` and :meth:`run` methods of -this class. +constructor, or by overriding the :meth:`~Thread.run` method in a subclass. +No other methods (except for the constructor) should be overridden in a +subclass. In other words, *only* override the :meth:`~Thread.__init__` +and :meth:`~Thread.run` methods of this class. Once a thread object is created, its activity must be started by calling the -thread's :meth:`start` method. This invokes the :meth:`run` method in a -separate thread of control. +thread's :meth:`~Thread.start` method. This invokes the :meth:`~Thread.run` +method in a separate thread of control. Once the thread's activity is started, the thread is considered 'alive'. It -stops being alive when its :meth:`run` method terminates -- either normally, or -by raising an unhandled exception. The :meth:`is_alive` method tests whether the -thread is alive. +stops being alive when its :meth:`~Thread.run` method terminates -- either +normally, or by raising an unhandled exception. The :meth:`~Thread.is_alive` +method tests whether the thread is alive. -Other threads can call a thread's :meth:`join` method. This blocks the calling -thread until the thread whose :meth:`join` method is called is terminated. +Other threads can call a thread's :meth:`~Thread.join` method. This blocks +the calling thread until the thread whose :meth:`~Thread.join` method is +called is terminated. A thread has a name. The name can be passed to the constructor, and read or -changed through the :attr:`name` attribute. +changed through the :attr:`~Thread.name` attribute. -A thread can be flagged as a "daemon thread". The significance of this flag is -that the entire Python program exits when only daemon threads are left. The -initial value is inherited from the creating thread. The flag can be set -through the :attr:`daemon` property. +A thread can be flagged as a "daemon thread". The significance of this flag +is that the entire Python program exits when only daemon threads are left. +The initial value is inherited from the creating thread. The flag can be +set through the :attr:`~Thread.daemon` property. There is a "main thread" object; this corresponds to the initial thread of control in the Python program. It is not a daemon thread. @@ -250,8 +251,8 @@ thread objects corresponding to "alien threads", which are threads of control started outside the threading module, such as directly from C code. Dummy thread objects have limited functionality; they are always considered alive and -daemonic, and cannot be :meth:`join`\ ed. They are never deleted, since it is -impossible to detect the termination of alien threads. +daemonic, and cannot be :meth:`~Thread.join`\ ed. They are never deleted, +since it is impossible to detect the termination of alien threads. .. class:: Thread(group=None, target=None, name=None, args=(), kwargs={}) @@ -282,7 +283,8 @@ Start the thread's activity. It must be called at most once per thread object. It arranges for the - object's :meth:`run` method to be invoked in a separate thread of control. + object's :meth:`~Thread.run` method to be invoked in a separate thread + of control. This method will raise a :exc:`RuntimeError` if called more than once on the same thread object. @@ -298,25 +300,27 @@ .. method:: join(timeout=None) - Wait until the thread terminates. This blocks the calling thread until the - thread whose :meth:`join` method is called terminates -- either normally - or through an unhandled exception -- or until the optional timeout occurs. + Wait until the thread terminates. This blocks the calling thread until + the thread whose :meth:`~Thread.join` method is called terminates -- either + normally or through an unhandled exception --, or until the optional + timeout occurs. When the *timeout* argument is present and not ``None``, it should be a floating point number specifying a timeout for the operation in seconds - (or fractions thereof). As :meth:`join` always returns ``None``, you must - call :meth:`is_alive` after :meth:`join` to decide whether a timeout - happened -- if the thread is still alive, the :meth:`join` call timed out. + (or fractions thereof). As :meth:`~Thread.join` always returns ``None``, + you must call :meth:`~Thread.is_alive` after :meth:`~Thread.join` to + decide whether a timeout happened -- if the thread is still alive, the + :meth:`~Thread.join` call timed out. When the *timeout* argument is not present or ``None``, the operation will block until the thread terminates. - A thread can be :meth:`join`\ ed many times. + A thread can be :meth:`~Thread.join`\ ed many times. - :meth:`join` raises a :exc:`RuntimeError` if an attempt is made to join - the current thread as that would cause a deadlock. It is also an error to - :meth:`join` a thread before it has been started and attempts to do so - raises the same exception. + :meth:`~Thread.join` raises a :exc:`RuntimeError` if an attempt is made + to join the current thread as that would cause a deadlock. It is also + an error to :meth:`~Thread.join` a thread before it has been started + and attempts to do so raise the same exception. .. attribute:: name @@ -334,7 +338,7 @@ The 'thread identifier' of this thread or ``None`` if the thread has not been started. This is a nonzero integer. See the - :func:`thread.get_ident()` function. Thread identifiers may be recycled + :func:`_thread.get_ident()` function. Thread identifiers may be recycled when a thread exits and another thread is created. The identifier is available even after the thread has exited. @@ -342,18 +346,18 @@ Return whether the thread is alive. - This method returns ``True`` just before the :meth:`run` method starts - until just after the :meth:`run` method terminates. The module function - :func:`.enumerate` returns a list of all alive threads. + This method returns ``True`` just before the :meth:`~Thread.run` method + starts until just after the :meth:`~Thread.run` method terminates. The + module function :func:`.enumerate` returns a list of all alive threads. .. attribute:: daemon A boolean value indicating whether this thread is a daemon thread (True) - or not (False). This must be set before :meth:`start` is called, + or not (False). This must be set before :meth:`~Thread.start` is called, otherwise :exc:`RuntimeError` is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and - therefore all threads created in the main thread default to :attr:`daemon` - = ``False``. + therefore all threads created in the main thread default to + :attr:`~Thread.daemon` = ``False``. The entire Python program exits when no alive non-daemon threads are left. @@ -375,19 +379,20 @@ extension module. A primitive lock is in one of two states, "locked" or "unlocked". It is created -in the unlocked state. It has two basic methods, :meth:`acquire` and -:meth:`release`. When the state is unlocked, :meth:`acquire` changes the state -to locked and returns immediately. When the state is locked, :meth:`acquire` -blocks until a call to :meth:`release` in another thread changes it to unlocked, -then the :meth:`acquire` call resets it to locked and returns. The -:meth:`release` method should only be called in the locked state; it changes the -state to unlocked and returns immediately. If an attempt is made to release an -unlocked lock, a :exc:`RuntimeError` will be raised. +in the unlocked state. It has two basic methods, :meth:`~Lock.acquire` and +:meth:`~Lock.release`. When the state is unlocked, :meth:`~Lock.acquire` +changes the state to locked and returns immediately. When the state is locked, +:meth:`~Lock.acquire` blocks until a call to :meth:`~Lock.release` in another +thread changes it to unlocked, then the :meth:`~Lock.acquire` call resets it +to locked and returns. The :meth:`~Lock.release` method should only be +called in the locked state; it changes the state to unlocked and returns +immediately. If an attempt is made to release an unlocked lock, a +:exc:`RuntimeError` will be raised. -When more than one thread is blocked in :meth:`acquire` waiting for the state to -turn to unlocked, only one thread proceeds when a :meth:`release` call resets -the state to unlocked; which one of the waiting threads proceeds is not defined, -and may vary across implementations. +When more than one thread is blocked in :meth:`~Lock.acquire` waiting for the +state to turn to unlocked, only one thread proceeds when a :meth:`~Lock.release` +call resets the state to unlocked; which one of the waiting threads proceeds +is not defined, and may vary across implementations. All methods are executed atomically. @@ -446,12 +451,12 @@ locks. In the locked state, some thread owns the lock; in the unlocked state, no thread owns it. -To lock the lock, a thread calls its :meth:`acquire` method; this returns once -the thread owns the lock. To unlock the lock, a thread calls its -:meth:`release` method. :meth:`acquire`/:meth:`release` call pairs may be -nested; only the final :meth:`release` (the :meth:`release` of the outermost -pair) resets the lock to unlocked and allows another thread blocked in -:meth:`acquire` to proceed. +To lock the lock, a thread calls its :meth:`~RLock.acquire` method; this +returns once the thread owns the lock. To unlock the lock, a thread calls +its :meth:`~Lock.release` method. :meth:`~Lock.acquire`/:meth:`~Lock.release` +call pairs may be nested; only the final :meth:`~Lock.release` (the +:meth:`~Lock.release` of the outermost pair) resets the lock to unlocked and +allows another thread blocked in :meth:`~Lock.acquire` to proceed. .. method:: RLock.acquire(blocking=True, timeout=-1) @@ -672,12 +677,14 @@ This is one of the oldest synchronization primitives in the history of computer science, invented by the early Dutch computer scientist Edsger W. Dijkstra (he -used :meth:`P` and :meth:`V` instead of :meth:`acquire` and :meth:`release`). +used the names ``P()`` and ``V()`` instead of :meth:`~Semaphore.acquire` and +:meth:`~Semaphore.release`). A semaphore manages an internal counter which is decremented by each -:meth:`acquire` call and incremented by each :meth:`release` call. The counter -can never go below zero; when :meth:`acquire` finds that it is zero, it blocks, -waiting until some other thread calls :meth:`release`. +:meth:`~Semaphore.acquire` call and incremented by each :meth:`~Semaphore.release` +call. The counter can never go below zero; when :meth:`~Semaphore.acquire` +finds that it is zero, it blocks, waiting until some other thread calls +:meth:`~Semaphore.release`. .. class:: Semaphore(value=1) @@ -693,11 +700,12 @@ When invoked without arguments: if the internal counter is larger than zero on entry, decrement it by one and return immediately. If it is zero on entry, block, waiting until some other thread has called - :meth:`release` to make it larger than zero. This is done with proper - interlocking so that if multiple :meth:`acquire` calls are blocked, - :meth:`release` will wake exactly one of them up. The implementation may - pick one at random, so the order in which blocked threads are awakened - should not be relied on. Returns true (or blocks indefinitely). + :meth:`~Semaphore.release` to make it larger than zero. This is done + with proper interlocking so that if multiple :meth:`acquire` calls are + blocked, :meth:`~Semaphore.release` will wake exactly one of them up. + The implementation may pick one at random, so the order in which + blocked threads are awakened should not be relied on. Returns + true (or blocks indefinitely). When invoked with *blocking* set to false, do not block. If a call without an argument would block, return false immediately; otherwise, @@ -753,8 +761,8 @@ thread signals an event and other threads wait for it. An event object manages an internal flag that can be set to true with the -:meth:`~Event.set` method and reset to false with the :meth:`clear` method. The -:meth:`wait` method blocks until the flag is true. +:meth:`~Event.set` method and reset to false with the :meth:`~Event.clear` +method. The :meth:`~Event.wait` method blocks until the flag is true. .. class:: Event() @@ -781,7 +789,7 @@ Block until the internal flag is true. If the internal flag is true on entry, return immediately. Otherwise, block until another thread calls - :meth:`set` to set the flag to true, or until the optional timeout occurs. + :meth:`.set` to set the flag to true, or until the optional timeout occurs. When the timeout argument is present and not ``None``, it should be a floating point number specifying a timeout for the operation in seconds @@ -837,8 +845,8 @@ This class provides a simple synchronization primitive for use by a fixed number of threads that need to wait for each other. Each of the threads tries to pass -the barrier by calling the :meth:`wait` method and will block until all of the -threads have made the call. At this points, the threads are released +the barrier by calling the :meth:`~Barrier.wait` method and will block until +all of the threads have made the call. At this points, the threads are released simultanously. The barrier can be reused any number of times for the same number of threads. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 22:57:06 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 10 Apr 2012 22:57:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Small_improveme?= =?utf8?q?nts_to_the_threading_docs=3A_better_publicize_support_for_the_wi?= =?utf8?q?th?= Message-ID: http://hg.python.org/cpython/rev/2040842626ba changeset: 76228:2040842626ba branch: 3.2 user: Antoine Pitrou date: Tue Apr 10 22:47:55 2012 +0200 summary: Small improvements to the threading docs: better publicize support for the with statement. files: Doc/library/threading.rst | 54 +++++++++++++++++---------- 1 files changed, 34 insertions(+), 20 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -389,6 +389,8 @@ immediately. If an attempt is made to release an unlocked lock, a :exc:`RuntimeError` will be raised. +Locks also support the :ref:`context manager protocol `. + When more than one thread is blocked in :meth:`~Lock.acquire` waiting for the state to turn to unlocked, only one thread proceeds when a :meth:`~Lock.release` call resets the state to unlocked; which one of the waiting threads proceeds @@ -429,7 +431,8 @@ .. method:: Lock.release() - Release a lock. + Release a lock. This can be called from any thread, not only the thread + which has acquired the lock. When the lock is locked, reset it to unlocked, and return. If any other threads are blocked waiting for the lock to become unlocked, allow exactly one of them @@ -458,6 +461,8 @@ :meth:`~Lock.release` of the outermost pair) resets the lock to unlocked and allows another thread blocked in :meth:`~Lock.acquire` to proceed. +Reentrant locks also support the :ref:`context manager protocol `. + .. method:: RLock.acquire(blocking=True, timeout=-1) @@ -512,10 +517,11 @@ several condition variables must share the same lock. The lock is part of the condition object: you don't have to track it separately. -A condition variable obeys the :term:`context manager` protocol: using the -``with`` statement acquires the associated lock for the duration of the -enclosed block. The :meth:`~Condition.acquire` and :meth:`~Condition.release` -methods also call the corresponding methods of the associated lock. +A condition variable obeys the :ref:`context manager protocol `: +using the ``with`` statement acquires the associated lock for the duration of +the enclosed block. The :meth:`~Condition.acquire` and +:meth:`~Condition.release` methods also call the corresponding methods of +the associated lock. Other methods must be called with the associated lock held. The :meth:`~Condition.wait` method releases the lock, and then blocks until @@ -686,6 +692,8 @@ finds that it is zero, it blocks, waiting until some other thread calls :meth:`~Semaphore.release`. +Semaphores also support the :ref:`context manager protocol `. + .. class:: Semaphore(value=1) @@ -742,11 +750,12 @@ Once spawned, worker threads call the semaphore's acquire and release methods when they need to connect to the server:: - pool_sema.acquire() - conn = connectdb() - ... use connection ... - conn.close() - pool_sema.release() + with pool_sema: + conn = connectdb() + try: + ... use connection ... + finally: + conn.close() The use of a bounded semaphore reduces the chance that a programming error which causes the semaphore to be released more than it's acquired will go undetected. @@ -947,19 +956,24 @@ All of the objects provided by this module that have :meth:`acquire` and :meth:`release` methods can be used as context managers for a :keyword:`with` -statement. The :meth:`acquire` method will be called when the block is entered, -and :meth:`release` will be called when the block is exited. +statement. The :meth:`acquire` method will be called when the block is +entered, and :meth:`release` will be called when the block is exited. Hence, +the following snippet:: + + with some_lock: + # do something... + +is equivalent to:: + + some_lock.acquire() + try: + # do something... + finally: + some_lock.release() Currently, :class:`Lock`, :class:`RLock`, :class:`Condition`, :class:`Semaphore`, and :class:`BoundedSemaphore` objects may be used as -:keyword:`with` statement context managers. For example:: - - import threading - - some_rlock = threading.RLock() - - with some_rlock: - print("some_rlock is locked while this executes") +:keyword:`with` statement context managers. .. _threaded-imports: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 22:57:07 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 10 Apr 2012 22:57:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge?= Message-ID: http://hg.python.org/cpython/rev/f43a278ab235 changeset: 76229:f43a278ab235 parent: 76222:64c26ac35b06 parent: 76228:2040842626ba user: Antoine Pitrou date: Tue Apr 10 22:51:26 2012 +0200 summary: Merge files: Doc/library/threading.rst | 296 ++++++++++++++----------- 1 files changed, 162 insertions(+), 134 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -218,30 +218,32 @@ This class represents an activity that is run in a separate thread of control. There are two ways to specify the activity: by passing a callable object to the -constructor, or by overriding the :meth:`run` method in a subclass. No other -methods (except for the constructor) should be overridden in a subclass. In -other words, *only* override the :meth:`__init__` and :meth:`run` methods of -this class. +constructor, or by overriding the :meth:`~Thread.run` method in a subclass. +No other methods (except for the constructor) should be overridden in a +subclass. In other words, *only* override the :meth:`~Thread.__init__` +and :meth:`~Thread.run` methods of this class. Once a thread object is created, its activity must be started by calling the -thread's :meth:`start` method. This invokes the :meth:`run` method in a -separate thread of control. +thread's :meth:`~Thread.start` method. This invokes the :meth:`~Thread.run` +method in a separate thread of control. Once the thread's activity is started, the thread is considered 'alive'. It -stops being alive when its :meth:`run` method terminates -- either normally, or -by raising an unhandled exception. The :meth:`is_alive` method tests whether the -thread is alive. +stops being alive when its :meth:`~Thread.run` method terminates -- either +normally, or by raising an unhandled exception. The :meth:`~Thread.is_alive` +method tests whether the thread is alive. -Other threads can call a thread's :meth:`join` method. This blocks the calling -thread until the thread whose :meth:`join` method is called is terminated. +Other threads can call a thread's :meth:`~Thread.join` method. This blocks +the calling thread until the thread whose :meth:`~Thread.join` method is +called is terminated. A thread has a name. The name can be passed to the constructor, and read or -changed through the :attr:`name` attribute. +changed through the :attr:`~Thread.name` attribute. A thread can be flagged as a "daemon thread". The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set -through the :attr:`daemon` property or the *daemon* constructor argument. +through the :attr:`~Thread.daemon` property or the *daemon* constructor +argument. There is a "main thread" object; this corresponds to the initial thread of control in the Python program. It is not a daemon thread. @@ -250,8 +252,8 @@ thread objects corresponding to "alien threads", which are threads of control started outside the threading module, such as directly from C code. Dummy thread objects have limited functionality; they are always considered alive and -daemonic, and cannot be :meth:`join`\ ed. They are never deleted, since it is -impossible to detect the termination of alien threads. +daemonic, and cannot be :meth:`~Thread.join`\ ed. They are never deleted, +since it is impossible to detect the termination of alien threads. .. class:: Thread(group=None, target=None, name=None, args=(), kwargs={}, @@ -292,7 +294,8 @@ Start the thread's activity. It must be called at most once per thread object. It arranges for the - object's :meth:`run` method to be invoked in a separate thread of control. + object's :meth:`~Thread.run` method to be invoked in a separate thread + of control. This method will raise a :exc:`RuntimeError` if called more than once on the same thread object. @@ -308,25 +311,27 @@ .. method:: join(timeout=None) - Wait until the thread terminates. This blocks the calling thread until the - thread whose :meth:`join` method is called terminates -- either normally - or through an unhandled exception -- or until the optional timeout occurs. + Wait until the thread terminates. This blocks the calling thread until + the thread whose :meth:`~Thread.join` method is called terminates -- either + normally or through an unhandled exception --, or until the optional + timeout occurs. When the *timeout* argument is present and not ``None``, it should be a floating point number specifying a timeout for the operation in seconds - (or fractions thereof). As :meth:`join` always returns ``None``, you must - call :meth:`is_alive` after :meth:`join` to decide whether a timeout - happened -- if the thread is still alive, the :meth:`join` call timed out. + (or fractions thereof). As :meth:`~Thread.join` always returns ``None``, + you must call :meth:`~Thread.is_alive` after :meth:`~Thread.join` to + decide whether a timeout happened -- if the thread is still alive, the + :meth:`~Thread.join` call timed out. When the *timeout* argument is not present or ``None``, the operation will block until the thread terminates. - A thread can be :meth:`join`\ ed many times. + A thread can be :meth:`~Thread.join`\ ed many times. - :meth:`join` raises a :exc:`RuntimeError` if an attempt is made to join - the current thread as that would cause a deadlock. It is also an error to - :meth:`join` a thread before it has been started and attempts to do so - raises the same exception. + :meth:`~Thread.join` raises a :exc:`RuntimeError` if an attempt is made + to join the current thread as that would cause a deadlock. It is also + an error to :meth:`~Thread.join` a thread before it has been started + and attempts to do so raise the same exception. .. attribute:: name @@ -343,27 +348,27 @@ .. attribute:: ident The 'thread identifier' of this thread or ``None`` if the thread has not - been started. This is a nonzero integer. See the :func:`get_ident()` - function. Thread identifiers may be recycled when a thread exits and - another thread is created. The identifier is available even after the - thread has exited. + been started. This is a nonzero integer. See the + :func:`_thread.get_ident()` function. Thread identifiers may be recycled + when a thread exits and another thread is created. The identifier is + available even after the thread has exited. .. method:: is_alive() Return whether the thread is alive. - This method returns ``True`` just before the :meth:`run` method starts - until just after the :meth:`run` method terminates. The module function - :func:`.enumerate` returns a list of all alive threads. + This method returns ``True`` just before the :meth:`~Thread.run` method + starts until just after the :meth:`~Thread.run` method terminates. The + module function :func:`.enumerate` returns a list of all alive threads. .. attribute:: daemon A boolean value indicating whether this thread is a daemon thread (True) - or not (False). This must be set before :meth:`start` is called, + or not (False). This must be set before :meth:`~Thread.start` is called, otherwise :exc:`RuntimeError` is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and - therefore all threads created in the main thread default to :attr:`daemon` - = ``False``. + therefore all threads created in the main thread default to + :attr:`~Thread.daemon` = ``False``. The entire Python program exits when no alive non-daemon threads are left. @@ -397,19 +402,22 @@ extension module. A primitive lock is in one of two states, "locked" or "unlocked". It is created -in the unlocked state. It has two basic methods, :meth:`acquire` and -:meth:`release`. When the state is unlocked, :meth:`acquire` changes the state -to locked and returns immediately. When the state is locked, :meth:`acquire` -blocks until a call to :meth:`release` in another thread changes it to unlocked, -then the :meth:`acquire` call resets it to locked and returns. The -:meth:`release` method should only be called in the locked state; it changes the -state to unlocked and returns immediately. If an attempt is made to release an -unlocked lock, a :exc:`RuntimeError` will be raised. +in the unlocked state. It has two basic methods, :meth:`~Lock.acquire` and +:meth:`~Lock.release`. When the state is unlocked, :meth:`~Lock.acquire` +changes the state to locked and returns immediately. When the state is locked, +:meth:`~Lock.acquire` blocks until a call to :meth:`~Lock.release` in another +thread changes it to unlocked, then the :meth:`~Lock.acquire` call resets it +to locked and returns. The :meth:`~Lock.release` method should only be +called in the locked state; it changes the state to unlocked and returns +immediately. If an attempt is made to release an unlocked lock, a +:exc:`RuntimeError` will be raised. -When more than one thread is blocked in :meth:`acquire` waiting for the state to -turn to unlocked, only one thread proceeds when a :meth:`release` call resets -the state to unlocked; which one of the waiting threads proceeds is not defined, -and may vary across implementations. +Locks also support the :ref:`context manager protocol `. + +When more than one thread is blocked in :meth:`~Lock.acquire` waiting for the +state to turn to unlocked, only one thread proceeds when a :meth:`~Lock.release` +call resets the state to unlocked; which one of the waiting threads proceeds +is not defined, and may vary across implementations. All methods are executed atomically. @@ -446,7 +454,8 @@ .. method:: Lock.release() - Release a lock. + Release a lock. This can be called from any thread, not only the thread + which has acquired the lock. When the lock is locked, reset it to unlocked, and return. If any other threads are blocked waiting for the lock to become unlocked, allow exactly one of them @@ -468,12 +477,14 @@ locks. In the locked state, some thread owns the lock; in the unlocked state, no thread owns it. -To lock the lock, a thread calls its :meth:`acquire` method; this returns once -the thread owns the lock. To unlock the lock, a thread calls its -:meth:`release` method. :meth:`acquire`/:meth:`release` call pairs may be -nested; only the final :meth:`release` (the :meth:`release` of the outermost -pair) resets the lock to unlocked and allows another thread blocked in -:meth:`acquire` to proceed. +To lock the lock, a thread calls its :meth:`~RLock.acquire` method; this +returns once the thread owns the lock. To unlock the lock, a thread calls +its :meth:`~Lock.release` method. :meth:`~Lock.acquire`/:meth:`~Lock.release` +call pairs may be nested; only the final :meth:`~Lock.release` (the +:meth:`~Lock.release` of the outermost pair) resets the lock to unlocked and +allows another thread blocked in :meth:`~Lock.acquire` to proceed. + +Reentrant locks also support the :ref:`context manager protocol `. .. method:: RLock.acquire(blocking=True, timeout=-1) @@ -525,62 +536,74 @@ ----------------- A condition variable is always associated with some kind of lock; this can be -passed in or one will be created by default. (Passing one in is useful when -several condition variables must share the same lock.) +passed in or one will be created by default. Passing one in is useful when +several condition variables must share the same lock. The lock is part of +the condition object: you don't have to track it separately. -A condition variable has :meth:`acquire` and :meth:`release` methods that call -the corresponding methods of the associated lock. It also has a :meth:`wait` -method, and :meth:`notify` and :meth:`notify_all` methods. These three must only -be called when the calling thread has acquired the lock, otherwise a -:exc:`RuntimeError` is raised. +A condition variable obeys the :ref:`context manager protocol `: +using the ``with`` statement acquires the associated lock for the duration of +the enclosed block. The :meth:`~Condition.acquire` and +:meth:`~Condition.release` methods also call the corresponding methods of +the associated lock. -The :meth:`wait` method releases the lock, and then blocks until it is awakened -by a :meth:`notify` or :meth:`notify_all` call for the same condition variable in -another thread. Once awakened, it re-acquires the lock and returns. It is also -possible to specify a timeout. +Other methods must be called with the associated lock held. The +:meth:`~Condition.wait` method releases the lock, and then blocks until +another thread awakens it by calling :meth:`~Condition.notify` or +:meth:`~Condition.notify_all`. Once awakened, :meth:`~Condition.wait` +re-acquires the lock and returns. It is also possible to specify a timeout. -The :meth:`notify` method wakes up one of the threads waiting for the condition -variable, if any are waiting. The :meth:`notify_all` method wakes up all threads -waiting for the condition variable. +The :meth:`~Condition.notify` method wakes up one of the threads waiting for +the condition variable, if any are waiting. The :meth:`~Condition.notify_all` +method wakes up all threads waiting for the condition variable. -Note: the :meth:`notify` and :meth:`notify_all` methods don't release the lock; -this means that the thread or threads awakened will not return from their -:meth:`wait` call immediately, but only when the thread that called -:meth:`notify` or :meth:`notify_all` finally relinquishes ownership of the lock. +Note: the :meth:`~Condition.notify` and :meth:`~Condition.notify_all` methods +don't release the lock; this means that the thread or threads awakened will +not return from their :meth:`~Condition.wait` call immediately, but only when +the thread that called :meth:`~Condition.notify` or :meth:`~Condition.notify_all` +finally relinquishes ownership of the lock. -Tip: the typical programming style using condition variables uses the lock to + +Usage +^^^^^ + +The typical programming style using condition variables uses the lock to synchronize access to some shared state; threads that are interested in a -particular change of state call :meth:`wait` repeatedly until they see the -desired state, while threads that modify the state call :meth:`notify` or -:meth:`notify_all` when they change the state in such a way that it could -possibly be a desired state for one of the waiters. For example, the following -code is a generic producer-consumer situation with unlimited buffer capacity:: +particular change of state call :meth:`~Condition.wait` repeatedly until they +see the desired state, while threads that modify the state call +:meth:`~Condition.notify` or :meth:`~Condition.notify_all` when they change +the state in such a way that it could possibly be a desired state for one +of the waiters. For example, the following code is a generic +producer-consumer situation with unlimited buffer capacity:: # Consume one item - cv.acquire() - while not an_item_is_available(): - cv.wait() - get_an_available_item() - cv.release() + with cv: + while not an_item_is_available(): + cv.wait() + get_an_available_item() # Produce one item - cv.acquire() - make_an_item_available() - cv.notify() - cv.release() + with cv: + make_an_item_available() -To choose between :meth:`notify` and :meth:`notify_all`, consider whether one -state change can be interesting for only one or several waiting threads. E.g. -in a typical producer-consumer situation, adding one item to the buffer only -needs to wake up one consumer thread. +The ``while`` loop checking for the application's condition is necessary +because :meth:`~Condition.wait` can return after an arbitrary long time, +and other threads may have exhausted the available items in between. This +is inherent to multi-threaded programming. The :meth:`~Condition.wait_for` +method can be used to automate the condition checking:: -Note: Condition variables can be, depending on the implementation, subject -to both spurious wakeups (when :meth:`wait` returns without a :meth:`notify` -call) and stolen wakeups (when another thread acquires the lock before the -awoken thread.) For this reason, it is always necessary to verify the state -the thread is waiting for when :meth:`wait` returns and optionally repeat -the call as often as necessary. + # Consume an item + with cv: + cv.wait_for(an_item_is_available) + get_an_available_item() +To choose between :meth:`~Condition.notify` and :meth:`~Condition.notify_all`, +consider whether one state change can be interesting for only one or several +waiting threads. E.g. in a typical producer-consumer situation, adding one +item to the buffer only needs to wake up one consumer thread. + + +Interface +^^^^^^^^^ .. class:: Condition(lock=None) @@ -648,12 +671,6 @@ held when called and is re-aquired on return. The predicate is evaluated with the lock held. - Using this method, the consumer example above can be written thus:: - - with cv: - cv.wait_for(an_item_is_available) - get_an_available_item() - .. versionadded:: 3.2 .. method:: notify(n=1) @@ -689,12 +706,16 @@ This is one of the oldest synchronization primitives in the history of computer science, invented by the early Dutch computer scientist Edsger W. Dijkstra (he -used :meth:`P` and :meth:`V` instead of :meth:`acquire` and :meth:`release`). +used the names ``P()`` and ``V()`` instead of :meth:`~Semaphore.acquire` and +:meth:`~Semaphore.release`). A semaphore manages an internal counter which is decremented by each -:meth:`acquire` call and incremented by each :meth:`release` call. The counter -can never go below zero; when :meth:`acquire` finds that it is zero, it blocks, -waiting until some other thread calls :meth:`release`. +:meth:`~Semaphore.acquire` call and incremented by each :meth:`~Semaphore.release` +call. The counter can never go below zero; when :meth:`~Semaphore.acquire` +finds that it is zero, it blocks, waiting until some other thread calls +:meth:`~Semaphore.release`. + +Semaphores also support the :ref:`context manager protocol `. .. class:: Semaphore(value=1) @@ -710,11 +731,12 @@ When invoked without arguments: if the internal counter is larger than zero on entry, decrement it by one and return immediately. If it is zero on entry, block, waiting until some other thread has called - :meth:`release` to make it larger than zero. This is done with proper - interlocking so that if multiple :meth:`acquire` calls are blocked, - :meth:`release` will wake exactly one of them up. The implementation may - pick one at random, so the order in which blocked threads are awakened - should not be relied on. Returns true (or blocks indefinitely). + :meth:`~Semaphore.release` to make it larger than zero. This is done + with proper interlocking so that if multiple :meth:`acquire` calls are + blocked, :meth:`~Semaphore.release` will wake exactly one of them up. + The implementation may pick one at random, so the order in which + blocked threads are awakened should not be relied on. Returns + true (or blocks indefinitely). When invoked with *blocking* set to false, do not block. If a call without an argument would block, return false immediately; otherwise, @@ -751,11 +773,12 @@ Once spawned, worker threads call the semaphore's acquire and release methods when they need to connect to the server:: - pool_sema.acquire() - conn = connectdb() - ... use connection ... - conn.close() - pool_sema.release() + with pool_sema: + conn = connectdb() + try: + ... use connection ... + finally: + conn.close() The use of a bounded semaphore reduces the chance that a programming error which causes the semaphore to be released more than it's acquired will go undetected. @@ -770,8 +793,8 @@ thread signals an event and other threads wait for it. An event object manages an internal flag that can be set to true with the -:meth:`~Event.set` method and reset to false with the :meth:`clear` method. The -:meth:`wait` method blocks until the flag is true. +:meth:`~Event.set` method and reset to false with the :meth:`~Event.clear` +method. The :meth:`~Event.wait` method blocks until the flag is true. .. class:: Event() @@ -798,7 +821,7 @@ Block until the internal flag is true. If the internal flag is true on entry, return immediately. Otherwise, block until another thread calls - :meth:`set` to set the flag to true, or until the optional timeout occurs. + :meth:`.set` to set the flag to true, or until the optional timeout occurs. When the timeout argument is present and not ``None``, it should be a floating point number specifying a timeout for the operation in seconds @@ -854,8 +877,8 @@ This class provides a simple synchronization primitive for use by a fixed number of threads that need to wait for each other. Each of the threads tries to pass -the barrier by calling the :meth:`wait` method and will block until all of the -threads have made the call. At this points, the threads are released +the barrier by calling the :meth:`~Barrier.wait` method and will block until +all of the threads have made the call. At this points, the threads are released simultanously. The barrier can be reused any number of times for the same number of threads. @@ -956,19 +979,24 @@ All of the objects provided by this module that have :meth:`acquire` and :meth:`release` methods can be used as context managers for a :keyword:`with` -statement. The :meth:`acquire` method will be called when the block is entered, -and :meth:`release` will be called when the block is exited. +statement. The :meth:`acquire` method will be called when the block is +entered, and :meth:`release` will be called when the block is exited. Hence, +the following snippet:: + + with some_lock: + # do something... + +is equivalent to:: + + some_lock.acquire() + try: + # do something... + finally: + some_lock.release() Currently, :class:`Lock`, :class:`RLock`, :class:`Condition`, :class:`Semaphore`, and :class:`BoundedSemaphore` objects may be used as -:keyword:`with` statement context managers. For example:: - - import threading - - some_rlock = threading.RLock() - - with some_rlock: - print("some_rlock is locked while this executes") +:keyword:`with` statement context managers. .. _threaded-imports: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 23:16:57 2012 From: python-checkins at python.org (stefan.krah) Date: Tue, 10 Apr 2012 23:16:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_stale_comment=2E?= Message-ID: http://hg.python.org/cpython/rev/155c735f1f6f changeset: 76230:155c735f1f6f user: Stefan Krah date: Tue Apr 10 23:08:29 2012 +0200 summary: Fix stale comment. files: Modules/_decimal/libmpdec/mpdecimal.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -458,6 +458,9 @@ * 1) MPD_MINALLOC <= result->alloc. * 2) 0 <= result->len <= result->alloc. * + * Case nwords == result->alloc: + * 'result' is unchanged. Return 1. + * * Case nwords > result->alloc: * Case realloc success: * The value of 'result' does not change. Return 1. @@ -465,13 +468,11 @@ * 'result' is NaN, status is updated with MPD_Malloc_error. Return 0. * * Case nwords < result->alloc: - * Case is_static_data or nwords < MPD_MINALLOC or realloc failure [1]: + * Case is_static_data or realloc failure [1]: * 'result' is unchanged. Return 1. * Case realloc success: * The value of result is undefined (expected). Return 1. * - * Case nwords == result->alloc: - * 'result' is unchanged. Return 1. * * [1] In that case the old (now oversized) area is still valid. */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 10 23:16:58 2012 From: python-checkins at python.org (stefan.krah) Date: Tue, 10 Apr 2012 23:16:58 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_1=29_Remove_claim_of_an_inp?= =?utf8?q?ut_invariant_that_is_only_true_for_static_mpd=5Ft=2E?= Message-ID: http://hg.python.org/cpython/rev/bcdd7246d6b3 changeset: 76231:bcdd7246d6b3 user: Stefan Krah date: Tue Apr 10 23:11:54 2012 +0200 summary: 1) Remove claim of an input invariant that is only true for static mpd_t. Resizing is used _inside_ libmpdec functions, and it is permitted to change x->alloc several times while setting x->len at the end of the function. Therefore, for dynamic mpd_t x->alloc can _temporarily_ drop below x->len. Of course the final result always has x->len <= x->alloc. For static mpd_t this cannot happen, since resizing to a smaller coefficient is a no-op. 2) Remove micro optimization in mpd_switch_to_dyn(): Previously only the valid initialized part of the existing coefficient up to x->len was copied to the new dynamic memory area. Now copying does the same as realloc() and the entire old memory area is copied. The rationale for this change is that it is no longer needed to memorize the explanation given in 1). files: Modules/_decimal/libmpdec/memory.c | 2 +- Modules/_decimal/libmpdec/mpdecimal.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Modules/_decimal/libmpdec/memory.c b/Modules/_decimal/libmpdec/memory.c --- a/Modules/_decimal/libmpdec/memory.c +++ b/Modules/_decimal/libmpdec/memory.c @@ -222,7 +222,7 @@ return 0; } - memcpy(result->data, p, result->len * (sizeof *result->data)); + memcpy(result->data, p, result->alloc * (sizeof *result->data)); result->alloc = nwords; mpd_set_dynamic_data(result); return 1; diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -454,9 +454,7 @@ * Resize the coefficient. Existing data up to 'nwords' is left untouched. * Return 1 on success, 0 otherwise. * - * Input invariants: - * 1) MPD_MINALLOC <= result->alloc. - * 2) 0 <= result->len <= result->alloc. + * Input invariant: MPD_MINALLOC <= result->alloc. * * Case nwords == result->alloc: * 'result' is unchanged. Return 1. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 00:43:00 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 11 Apr 2012 00:43:00 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_info_about_slee?= =?utf8?q?p/suspend?= Message-ID: http://hg.python.org/peps/rev/2924271fe8d2 changeset: 4212:2924271fe8d2 user: Victor Stinner date: Wed Apr 11 00:42:54 2012 +0200 summary: PEP 418: Add info about sleep/suspend files: pep-0418.txt | 41 ++++++++++++++++++++++++++++----------- 1 files changed, 29 insertions(+), 12 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -307,18 +307,18 @@ Monotonic clocks ---------------- -========================= =============== ================ ==================== -Name Resolution Adjusted by NTP? Action on suspend -========================= =============== ================ ==================== -CLOCK_MONOTONIC_RAW 1 ns No Stopped -gethrtime 1 ns No Not stopped -CLOCK_HIGHRES 1 ns No ? -CLOCK_MONOTONIC 1 ns Slewed on Linux Stopped on Linux -mach_absolute_time() 1 ns No ? -QueryPerformanceCounter() \- No Accuracy issue -GetTickCount[64]() 1 ms No Include suspend time -timeGetTime() 1 ms No ? -========================= =============== ================ ==================== +========================= ========== =============== ============= =============== +Name Resolution Adjusted Include sleep Include suspend +========================= ========== =============== ============= =============== +gethrtime 1 ns No Yes Yes +CLOCK_HIGHRES 1 ns No Yes ? +CLOCK_MONOTONIC 1 ns Slewed on Linux Yes No +CLOCK_MONOTONIC_RAW 1 ns No Yes No +mach_absolute_time() 1 ns No ? ? +QueryPerformanceCounter() \- No Yes ? +GetTickCount[64]() 1 ms No Yes Yes +timeGetTime() 1 ms No Yes ? +========================= ========== =============== ============= =============== Examples of clock accuracy on x86_64: @@ -515,6 +515,9 @@ GetTickCount(), timeGetTime() rolls over after 2^32 milliseconds (49.7 days). +The elapsed time retrieved by timeGetTime() includes time the system spends in +sleep. + The default precision of the timeGetTime function can be five milliseconds or more, depending on the machine. @@ -805,6 +808,8 @@ Linux ----- +sleep() is not affected by system clock update. + On Linux, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW includes time the system spends in sleep; but it does not include time spent in hibernation (ACPI S3 mode). If the system clock jumps backward, CLOCK_MONOTONIC and @@ -815,6 +820,18 @@ spent in suspend. Read also `Waking systems from suspend `_ (March, 2011). +Other operating systems +----------------------- + +On Windows, GetTickCount() and GetTickCount64() include time the system +spends in sleep; sleep() is not affected by system clock update. + +On FreeBSD 8, CLOCK_MONOTONIC include time the system spends in sleep; sleep() +is not affected by system clock update. + +On OpenIndiana, CLOCK_MONOTONIC include time the system spends in sleep; +sleep() is not affected by system clock update. + Sleeping ======== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 11 00:58:38 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 11 Apr 2012 00:58:38 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_mach=5Fabsolute=5Ft?= =?utf8?q?ime=28=29_doesn=27t_include_suspend_time?= Message-ID: http://hg.python.org/peps/rev/7f7810f0b217 changeset: 4213:7f7810f0b217 user: Victor Stinner date: Wed Apr 11 00:58:33 2012 +0200 summary: PEP 418: mach_absolute_time() doesn't include suspend time files: pep-0418.txt | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -314,7 +314,7 @@ CLOCK_HIGHRES 1 ns No Yes ? CLOCK_MONOTONIC 1 ns Slewed on Linux Yes No CLOCK_MONOTONIC_RAW 1 ns No Yes No -mach_absolute_time() 1 ns No ? ? +mach_absolute_time() 1 ns No Yes No QueryPerformanceCounter() \- No Yes ? GetTickCount[64]() 1 ms No Yes Yes timeGetTime() 1 ms No Yes ? @@ -832,6 +832,10 @@ On OpenIndiana, CLOCK_MONOTONIC include time the system spends in sleep; sleep() is not affected by system clock update. +On Mac OS X, mach_absolute_time() include time the system spends in sleep; +sleep() is not affected by system clock update. Sleep is interrupted during +suspend. + Sleeping ======== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 11 01:23:34 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 11 Apr 2012 01:23:34 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_a_linkg_to_GetS?= =?utf8?q?ystemTimeAsFileTime=28=29_doc?= Message-ID: http://hg.python.org/peps/rev/960097b549b6 changeset: 4214:960097b549b6 user: Victor Stinner date: Wed Apr 11 01:23:28 2012 +0200 summary: PEP 418: Add a linkg to GetSystemTimeAsFileTime() doc files: pep-0418.txt | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -611,6 +611,9 @@ * ftime(): 1 millisecond * time(): 1 second +Read the `GetSystemTimeAsFileTime() documentation +`_. + The system time can be set using SetSystemTime(). System time on UNIX -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 11 01:37:09 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 11 Apr 2012 01:37:09 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Rewrite_the_rationa?= =?utf8?q?le?= Message-ID: http://hg.python.org/peps/rev/48d46f2f86b0 changeset: 4215:48d46f2f86b0 user: Victor Stinner date: Wed Apr 11 01:37:04 2012 +0200 summary: PEP 418: Rewrite the rationale files: pep-0418.txt | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -19,14 +19,16 @@ Rationale ========= -Use cases: +If a program uses the system clock to schedule events or to implement a +timeout, it will not run events at the right moment or stop the timeout too +early or too late when the system clock is set manually or adjusted +automatically by NTP. A monotonic clock should be used instead to not be +affected by system clock updates. -* Display the current time to a human (e.g. display a calendar or draw - a wall clock): use system clock, i.e. time.time() or - datetime.datetime.now(). -* Event scheduler, timeout: time.monotonic(). -* Benchmark, profiling: time.clock() on Windows, time.monotonic(), - or fallback to time.time() +Clocks: + + * time.time(): system clock + * time.monotonic(): monotonic clock Functions -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 11 02:04:55 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 11 Apr 2012 02:04:55 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Rewrite_time=2Emono?= =?utf8?q?tonic=28=29_definition?= Message-ID: http://hg.python.org/peps/rev/310548c3a12c changeset: 4216:310548c3a12c user: Victor Stinner date: Wed Apr 11 02:04:51 2012 +0200 summary: PEP 418: Rewrite time.monotonic() definition files: pep-0418.txt | 9 +++------ 1 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -82,12 +82,9 @@ time.monotonic() ---------------- -Monotonic clock, cannot go backward. Its rate may be adjusted by NTP. The -reference point of the returned value is undefined so only the difference of -consecutive calls is valid. - -The elapsed time may or may not include time the system spends in -sleep or hibernation; this depends on the operating system. +Monotonic clock, cannot go backward. It is not affected by system clock +updates. The reference point of the returned value is undefined so only the +difference of consecutive calls is valid. Availability: Windows, Mac OS X, Unix. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 11 03:06:00 2012 From: python-checkins at python.org (brett.cannon) Date: Wed, 11 Apr 2012 03:06:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Make_the_trace_module_ignor?= =?utf8?q?e_modules_whose_names_start_with_=22=3C=22_and?= Message-ID: http://hg.python.org/cpython/rev/8a47d2322df0 changeset: 76232:8a47d2322df0 user: Brett Cannon date: Tue Apr 10 21:05:53 2012 -0400 summary: Make the trace module ignore modules whose names start with "<" and end with ">", i.e. follow convention. files: Lib/trace.py | 3 +-- Misc/NEWS | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/trace.py b/Lib/trace.py --- a/Lib/trace.py +++ b/Lib/trace.py @@ -244,8 +244,7 @@ """Return True if the filename does not refer to a file we want to have reported. """ - return (filename == "" or - filename.startswith("') def update(self, other): """Merge in the data from another CoverageResults""" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- trace.CoverageResults.is_ignored_filename() now ignores any name that starts + with "<" and ends with ">" instead of special-casing "" and + " results for 8a47d2322df0 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogEdjPg1', '-x'] From python-checkins at python.org Wed Apr 11 12:46:23 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 12:46:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Issue_=2314387_?= =?utf8?q?=3A_undefine_=27small=27_so_that_it_doesn=27t_clash_with_Windows?= =?utf8?q?_headers=2E?= Message-ID: http://hg.python.org/cpython/rev/f91ecbc8bafc changeset: 76233:f91ecbc8bafc branch: 3.2 parent: 75820:b5e52995f76a user: Kristj?n Valur J?nsson date: Thu Mar 22 23:10:37 2012 +0000 summary: Issue #14387 : undefine 'small' so that it doesn't clash with Windows headers. files: Include/accu.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Include/accu.h b/Include/accu.h --- a/Include/accu.h +++ b/Include/accu.h @@ -16,6 +16,8 @@ extern "C" { #endif +#undef small /* defined by some Windows headers */ + typedef struct { PyObject *large; /* A list of previously accumulated large strings */ PyObject *small; /* Pending small strings */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 12:46:24 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 12:46:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_News_entry_for_?= =?utf8?q?f91ecbc8bafc=2E?= Message-ID: http://hg.python.org/cpython/rev/2fed9ece9cdc changeset: 76234:2fed9ece9cdc branch: 3.2 user: Georg Brandl date: Tue Apr 10 19:27:27 2012 +0200 summary: News entry for f91ecbc8bafc. files: Misc/NEWS | 12 +++++++----- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,13 +5,13 @@ What's New in Python 3.2.3? =========================== -*Release date: XX-Mar-2012* - -Core and Builtins ------------------ - -Library -------- +*Release date: 10-Apr-2012* + +Build +----- + +- Issue #14387: Work around a problem building extension modules under Windows + by undefining ``small`` before use in the Python headers. What's New in Python 3.2.3 release candidate 2? -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 12:46:25 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 12:46:25 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogQnVtcCB0byAzLjIu?= =?utf8?q?3_final=2E?= Message-ID: http://hg.python.org/cpython/rev/90ba44e02dd8 changeset: 76235:90ba44e02dd8 branch: 3.2 user: Georg Brandl date: Tue Apr 10 19:28:09 2012 +0200 summary: Bump to 3.2.3 final. files: Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/RPM/python-3.2.spec | 2 +- README | 4 ++-- 5 files changed, 8 insertions(+), 8 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 2 #define PY_MICRO_VERSION 3 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.2.3rc2+" +#define PY_VERSION "3.2.3" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.2.3rc2" +__version__ = "3.2.3" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.2.3rc2" +IDLE_VERSION = "3.2.3" diff --git a/Misc/RPM/python-3.2.spec b/Misc/RPM/python-3.2.spec --- a/Misc/RPM/python-3.2.spec +++ b/Misc/RPM/python-3.2.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.2.3rc2 +%define version 3.2.3 %define libvers 3.2 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.2.3 rc2 -================================ +This is Python version 3.2.3 +============================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Python Software Foundation. All rights reserved. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 12:46:25 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 12:46:25 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogQWRkIDMuMi4zcmMy?= =?utf8?q?_uuid=2E?= Message-ID: http://hg.python.org/cpython/rev/71600b5cd9c1 changeset: 76236:71600b5cd9c1 branch: 3.2 parent: 75820:b5e52995f76a user: Martin v. L?wis date: Sun Mar 18 20:39:19 2012 +0100 summary: Add 3.2.3rc2 uuid. files: Tools/msi/uuids.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Tools/msi/uuids.py b/Tools/msi/uuids.py --- a/Tools/msi/uuids.py +++ b/Tools/msi/uuids.py @@ -93,6 +93,7 @@ '3.2.2121':'{DFB29A53-ACC4-44e6-85A6-D0DA26FE8E4E}', # 3.2.2rc1 '3.2.2150':'{4CDE3168-D060-4b7c-BC74-4D8F9BB01AFD}', # 3.2.2 '3.2.3121':'{B8E8CFF7-E4C6-4a7c-9F06-BB3A8B75DDA8}', # 3.2.3rc1 + '3.2.3122':'{E8DCD3E0-12B6-4fb7-9DB5-543C2E67372E}', # 3.2.3rc2 '3.2.3150':'{789C9644-9F82-44d3-B4CA-AC31F46F5882}', # 3.2.3 } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 12:46:26 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 12:46:26 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMik6?= =?utf8?q?_Merge=2E?= Message-ID: http://hg.python.org/cpython/rev/3d0686d90f55 changeset: 76237:3d0686d90f55 branch: 3.2 tag: v3.2.3 parent: 76235:90ba44e02dd8 parent: 76236:71600b5cd9c1 user: Georg Brandl date: Tue Apr 10 19:30:22 2012 +0200 summary: Merge. files: Tools/msi/uuids.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Tools/msi/uuids.py b/Tools/msi/uuids.py --- a/Tools/msi/uuids.py +++ b/Tools/msi/uuids.py @@ -93,6 +93,7 @@ '3.2.2121':'{DFB29A53-ACC4-44e6-85A6-D0DA26FE8E4E}', # 3.2.2rc1 '3.2.2150':'{4CDE3168-D060-4b7c-BC74-4D8F9BB01AFD}', # 3.2.2 '3.2.3121':'{B8E8CFF7-E4C6-4a7c-9F06-BB3A8B75DDA8}', # 3.2.3rc1 + '3.2.3122':'{E8DCD3E0-12B6-4fb7-9DB5-543C2E67372E}', # 3.2.3rc2 '3.2.3150':'{789C9644-9F82-44d3-B4CA-AC31F46F5882}', # 3.2.3 } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 12:46:27 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 12:46:27 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Added_tag_v3=2E?= =?utf8?q?2=2E3_for_changeset_3d0686d90f55?= Message-ID: http://hg.python.org/cpython/rev/86d1421a552c changeset: 76238:86d1421a552c branch: 3.2 user: Georg Brandl date: Tue Apr 10 19:30:26 2012 +0200 summary: Added tag v3.2.3 for changeset 3d0686d90f55 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -96,3 +96,4 @@ 137e45f15c0bd262c9ad4c032d97425bc0589456 v3.2.2 7085403daf439adb3f9e70ef13f6bedb1c447376 v3.2.3rc1 428f05cb7277e1d42bb9dd8d1af6b6270ebc6112 v3.2.3rc2 +3d0686d90f55a78f96d9403da2c52dc2411419d0 v3.2.3 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 12:46:27 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 12:46:27 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Post-release_up?= =?utf8?q?date=2E?= Message-ID: http://hg.python.org/cpython/rev/383e328ade62 changeset: 76239:383e328ade62 branch: 3.2 user: Georg Brandl date: Wed Apr 11 12:45:12 2012 +0200 summary: Post-release update. files: Include/patchlevel.h | 2 +- 1 files changed, 1 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 0 /* Version as a string */ -#define PY_VERSION "3.2.3" +#define PY_VERSION "3.2.3+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 12:46:28 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 12:46:28 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMik6?= =?utf8?q?_Merge_3=2E2=2E3_release_clone=2E?= Message-ID: http://hg.python.org/cpython/rev/6b9e24539a70 changeset: 76240:6b9e24539a70 branch: 3.2 parent: 76228:2040842626ba parent: 76239:383e328ade62 user: Georg Brandl date: Wed Apr 11 12:46:24 2012 +0200 summary: Merge 3.2.3 release clone. files: .hgtags | 1 + Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 12 +++++++----- Misc/RPM/python-3.2.spec | 2 +- README | 4 ++-- Tools/msi/uuids.py | 1 + 8 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -98,3 +98,4 @@ 137e45f15c0bd262c9ad4c032d97425bc0589456 v3.2.2 7085403daf439adb3f9e70ef13f6bedb1c447376 v3.2.3rc1 428f05cb7277e1d42bb9dd8d1af6b6270ebc6112 v3.2.3rc2 +3d0686d90f55a78f96d9403da2c52dc2411419d0 v3.2.3 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 2 #define PY_MICRO_VERSION 3 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.2.3rc2+" +#define PY_VERSION "3.2.3+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.2.3rc2" +__version__ = "3.2.3" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.2.3rc2" +IDLE_VERSION = "3.2.3" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -167,13 +167,13 @@ What's New in Python 3.2.3? =========================== -*Release date: XX-Mar-2012* - -Core and Builtins ------------------ - -Library -------- +*Release date: 10-Apr-2012* + +Build +----- + +- Issue #14387: Work around a problem building extension modules under Windows + by undefining ``small`` before use in the Python headers. What's New in Python 3.2.3 release candidate 2? diff --git a/Misc/RPM/python-3.2.spec b/Misc/RPM/python-3.2.spec --- a/Misc/RPM/python-3.2.spec +++ b/Misc/RPM/python-3.2.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.2.3rc2 +%define version 3.2.3 %define libvers 3.2 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.2.3 rc2 -================================ +This is Python version 3.2.3 +============================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Python Software Foundation. All rights reserved. diff --git a/Tools/msi/uuids.py b/Tools/msi/uuids.py --- a/Tools/msi/uuids.py +++ b/Tools/msi/uuids.py @@ -93,6 +93,7 @@ '3.2.2121':'{DFB29A53-ACC4-44e6-85A6-D0DA26FE8E4E}', # 3.2.2rc1 '3.2.2150':'{4CDE3168-D060-4b7c-BC74-4D8F9BB01AFD}', # 3.2.2 '3.2.3121':'{B8E8CFF7-E4C6-4a7c-9F06-BB3A8B75DDA8}', # 3.2.3rc1 + '3.2.3122':'{E8DCD3E0-12B6-4fb7-9DB5-543C2E67372E}', # 3.2.3rc2 '3.2.3150':'{789C9644-9F82-44d3-B4CA-AC31F46F5882}', # 3.2.3 } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 13:06:58 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 11 Apr 2012 13:06:58 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_time=2Eclock=28?= =?utf8?q?=29=2C_fix_typos=2C_mention_issue_=2314309?= Message-ID: http://hg.python.org/peps/rev/cf2a8763616b changeset: 4217:cf2a8763616b user: Victor Stinner date: Wed Apr 11 13:06:33 2012 +0200 summary: PEP 418: Add time.clock(), fix typos, mention issue #14309 files: pep-0418.txt | 62 ++++++++++++++++++++++++++++++++------- 1 files changed, 51 insertions(+), 11 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -84,7 +84,7 @@ Monotonic clock, cannot go backward. It is not affected by system clock updates. The reference point of the returned value is undefined so only the -difference of consecutive calls is valid. +difference between consecutive calls is valid. Availability: Windows, Mac OS X, Unix. @@ -185,6 +185,43 @@ _time.sleep(seconds) +time.clock() +------------ + +On Unix, return the current processor time as a floating point number expressed +in seconds. The precision, and in fact the very definition of the meaning of +"processor time", depends on that of the C function of the same name, but in any +case, this is the function to use for benchmarking Python or timing algorithms. + +On Windows, this function returns wall-clock seconds elapsed since the first +call to this function, as a floating point number, based on the Win32 function +``QueryPerformanceCounter()``. The resolution is typically better than one +microsecond. + +Pseudo-code [#pseudo]_:: + + if os.name == 'nt': + def clock(): + if clock.use_performance_counter: + if clock.perf_frequency is None: + try: + clock.perf_frequency = float(_time.QueryPerformanceFrequency()) + except OSError: + # QueryPerformanceFrequency() fails if the installed + # hardware does not support a high-resolution performance + # counter + clock.use_performance_counter = False + else: + return _time.QueryPerformanceCounter() / clock.perf_frequency + else: + return _time.QueryPerformanceCounter() / clock.perf_frequency + return _time.clock() + clock.use_performance_counter = True + clock.perf_frequency = None + else: + clock = _time.clock + + time.get_clock_info(name) ------------------------- @@ -224,7 +261,7 @@ Accuracy -------- -The accuracy is the effective smallest difference of two timestamps of the +The accuracy is the effective smallest difference between two timestamps of the clock. It does not reflect the stability the clock rate. For example, QueryPerformanceCounter() has a good accuracy but is known to not have a steady rate. @@ -260,7 +297,7 @@ processor clock cycle, but now the rate is usually constant (even if the processor changes frequency) and usually equals the maximum processor frequency. Multiple cores having different TSC values. Hibernation of system - will reset TSC value. The instructor RDTSC can be used to read this counter. + will reset TSC value. The RDTSC instruction can be used to read this counter. CPU frequency scaling for power saving. * ACPI PMTMR (power management timer): ACPI 24-bit timer with a frequency of 3.5 MHz (3,579,545 Hz). HPET can cause around 3 seconds of drift per day. @@ -635,7 +672,7 @@ Process time ------------ -The process time cannot be set. It is not monotonic: the clocks stop while the +The process time cannot be set. It It is not monotonic: the clocks stop while the process is idle. ========================= =============== @@ -965,8 +1002,8 @@ use another clock, display an error, or do something else -One function choosing the clock from a list of constrains ---------------------------------------------------------- +One function choosing the clock from a list of constraints +---------------------------------------------------------- ``time.get_clock(*flags)`` with the following flags: @@ -1044,25 +1081,25 @@ ================================= Performance counter used for benchmarking and profiling. The reference point of -the returned value is undefined so only the difference of consecutive calls is +the returned value is undefined so only the difference between consecutive calls is valid and is number of seconds. Pseudo-code:: def perf_counter(): if perf_counter.use_performance_counter: - if perf_counter.cpu_frequency is None: + if perf_counter.perf_frequency is None: try: - perf_counter.cpu_frequency = float(_time.QueryPerformanceFrequency()) + perf_counter.perf_frequency = float(_time.QueryPerformanceFrequency()) except OSError: # QueryPerformanceFrequency() fails if the installed # hardware does not support a high-resolution performance # counter perf_counter.use_performance_counter = False else: - return _time.QueryPerformanceCounter() / perf_counter.cpu_frequency + return _time.QueryPerformanceCounter() / perf_counter.perf_frequency else: - return _time.QueryPerformanceCounter() / perf_counter.cpu_frequency + return _time.QueryPerformanceCounter() / perf_counter.perf_frequency if perf_counter.use_monotonic: # Monotonic clock is preferred over system clock try: @@ -1072,7 +1109,7 @@ return time.time() perf_counter.use_performance_counter = (os.name == 'nt') if perf_counter.use_performance_counter: - perf_counter.cpu_frequency = None + perf_counter.perf_frequency = None perf_counter.use_monotonic = hasattr(time, 'monotonic') Other names proposed for time.perf_counter(): @@ -1103,6 +1140,8 @@ `_ * `Issue #14222: Use time.steady() to implement timeout `_ +* `Issue #14309: Deprecate time.clock() + `_ * `Issue #14397: Use GetTickCount/GetTickCount64 instead of QueryPerformanceCounter for monotonic clock `_ -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 11 14:04:45 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 11 Apr 2012 14:04:45 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Mention_SMI_issues?= Message-ID: http://hg.python.org/peps/rev/4ab6524c1e08 changeset: 4218:4ab6524c1e08 user: Victor Stinner date: Wed Apr 11 14:04:23 2012 +0200 summary: PEP 418: Mention SMI issues files: pep-0418.txt | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1223,6 +1223,19 @@ bits of time * `Win32 Performance Measurement Options `_ by Matthew Wilson, May 01, 2003 +* System Management Interrupt (SMI) issues: + + * `System Management Interrupt Free Hardware + `_ + (Keith Mannthey, 2009) + * `IBM Real-Time "SMI Free" mode driver + `_ + * `Fixing Realtime problems caused by SMI on Ubuntu + `_ + * `[RFC] simple SMI detector + `_ + * `[PATCH 2.6.34-rc3] A nonintrusive SMI sniffer for x86. + `_ Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 11 16:41:35 2012 From: python-checkins at python.org (martin.v.loewis) Date: Wed, 11 Apr 2012 16:41:35 +0200 (CEST) Subject: [Python-checkins] r88946 - in tracker/instances/python-dev: detectors/userauditor.py html/issue.item.html html/user.item.html schema.py Message-ID: <3VSScb637hzMS4@mail.python.org> Author: martin.v.loewis Date: Wed Apr 11 16:41:35 2012 New Revision: 88946 Log: Issue 456: Provide home page URL for committer. Modified: tracker/instances/python-dev/detectors/userauditor.py tracker/instances/python-dev/html/issue.item.html tracker/instances/python-dev/html/user.item.html tracker/instances/python-dev/schema.py Modified: tracker/instances/python-dev/detectors/userauditor.py ============================================================================== --- tracker/instances/python-dev/detectors/userauditor.py (original) +++ tracker/instances/python-dev/detectors/userauditor.py Wed Apr 11 16:41:35 2012 @@ -20,6 +20,8 @@ # #$Id: userauditor.py,v 1.3 2006/09/18 03:24:38 tobias-herp Exp $ +import urlparse + def audit_user_fields(db, cl, nodeid, newvalues): ''' Make sure user properties are valid. @@ -39,6 +41,10 @@ if not "admin" in [x.lower().strip() for x in cl.get(nodeid, 'roles').split(",")]: raise ValueError, "Only Admins may assign the Admin role!" + if newvalues.get('homepage'): + scheme = urlparse.urlparse(newvalues['homepage'])[0] + if scheme not in ('http', 'https'): + raise ValueError, "Invalid URL scheme in homepage URL" def init(db): # fire before changes are made Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Wed Apr 11 16:41:35 2012 @@ -310,7 +310,10 @@ - (view) Author: () + i18n:name="author" /> () * (Python committer) Modified: tracker/instances/python-dev/html/user.item.html ============================================================================== --- tracker/instances/python-dev/html/user.item.html (original) +++ tracker/instances/python-dev/html/user.item.html Wed Apr 11 16:41:35 2012 @@ -108,6 +108,11 @@ + + Home page + + + Contributor Form Received Modified: tracker/instances/python-dev/schema.py ============================================================================== --- tracker/instances/python-dev/schema.py (original) +++ tracker/instances/python-dev/schema.py Wed Apr 11 16:41:35 2012 @@ -96,6 +96,7 @@ contrib_form_date=Date(), openids=String(), # space separated list iscommitter=Boolean(), + homepage=String(), ) user.setkey("username") db.security.addPermission(name='Register', klass='user', From python-checkins at python.org Wed Apr 11 17:06:08 2012 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 11 Apr 2012 17:06:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_use_assertWarns_instead_of_?= =?utf8?q?check=5Fwarnings_-_Issue14341?= Message-ID: http://hg.python.org/cpython/rev/751c7b81f6ee changeset: 76241:751c7b81f6ee parent: 76232:8a47d2322df0 user: Senthil Kumaran date: Wed Apr 11 23:05:49 2012 +0800 summary: use assertWarns instead of check_warnings - Issue14341 files: Lib/test/test_urllib2.py | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -618,21 +618,23 @@ def test_method_deprecations(self): req = Request("http://www.example.com") - with support.check_warnings(('', DeprecationWarning)): + + with self.assertWarns(DeprecationWarning) as cm: req.add_data("data") - with support.check_warnings(('', DeprecationWarning)): + with self.assertWarns(DeprecationWarning) as cm: req.has_data() - with support.check_warnings(('', DeprecationWarning)): + with self.assertWarns(DeprecationWarning) as cm: req.get_data() - with support.check_warnings(('', DeprecationWarning)): + with self.assertWarns(DeprecationWarning) as cm: req.get_host() - with support.check_warnings(('', DeprecationWarning)): + with self.assertWarns(DeprecationWarning) as cm: req.get_selector() - with support.check_warnings(('', DeprecationWarning)): + with self.assertWarns(DeprecationWarning) as cm: req.is_unverifiable() - with support.check_warnings(('', DeprecationWarning)): + with self.assertWarns(DeprecationWarning) as cm: req.get_origin_req_host() + def sanepathname2url(path): try: path.encode("utf-8") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 18:36:47 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 18:36:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Closes_=2314545?= =?utf8?q?=3A_make_clearer_what_was_added=2E?= Message-ID: http://hg.python.org/cpython/rev/2776ccf003cc changeset: 76242:2776ccf003cc branch: 3.2 parent: 76240:6b9e24539a70 user: Georg Brandl date: Wed Apr 11 18:33:17 2012 +0200 summary: Closes #14545: make clearer what was added. files: Doc/library/html.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/html.rst b/Doc/library/html.rst --- a/Doc/library/html.rst +++ b/Doc/library/html.rst @@ -4,8 +4,6 @@ .. module:: html :synopsis: Helpers for manipulating HTML. -.. versionadded:: 3.2 - **Source code:** :source:`Lib/html/__init__.py` -------------- @@ -19,3 +17,5 @@ characters in HTML. If the optional flag *quote* is true, the characters (``"``) and (``'``) are also translated; this helps for inclusion in an HTML attribute value delimited by quotes, as in ````. + + .. versionadded:: 3.2 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 18:36:49 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 18:36:49 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/e5cca3cdf210 changeset: 76243:e5cca3cdf210 parent: 76241:751c7b81f6ee parent: 76240:6b9e24539a70 user: Georg Brandl date: Wed Apr 11 18:36:46 2012 +0200 summary: Merge 3.2 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -98,5 +98,6 @@ 137e45f15c0bd262c9ad4c032d97425bc0589456 v3.2.2 7085403daf439adb3f9e70ef13f6bedb1c447376 v3.2.3rc1 428f05cb7277e1d42bb9dd8d1af6b6270ebc6112 v3.2.3rc2 +3d0686d90f55a78f96d9403da2c52dc2411419d0 v3.2.3 f1a9a6505731714f0e157453ff850e3b71615c45 v3.3.0a1 2f69db52d6de306cdaef0a0cc00cc823fb350b01 v3.3.0a2 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 18:36:50 2012 From: python-checkins at python.org (georg.brandl) Date: Wed, 11 Apr 2012 18:36:50 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314545=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/f5f8a7fd881c changeset: 76244:f5f8a7fd881c parent: 76243:e5cca3cdf210 parent: 76242:2776ccf003cc user: Georg Brandl date: Wed Apr 11 18:36:58 2012 +0200 summary: #14545: merge 3.2 files: Doc/library/html.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/html.rst b/Doc/library/html.rst --- a/Doc/library/html.rst +++ b/Doc/library/html.rst @@ -4,8 +4,6 @@ .. module:: html :synopsis: Helpers for manipulating HTML. -.. versionadded:: 3.2 - **Source code:** :source:`Lib/html/__init__.py` -------------- @@ -19,3 +17,5 @@ characters in HTML. If the optional flag *quote* is true, the characters (``"``) and (``'``) are also translated; this helps for inclusion in an HTML attribute value delimited by quotes, as in ````. + + .. versionadded:: 3.2 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 19:44:11 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 11 Apr 2012 19:44:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Improve_the_threading=2ECondition_docs=2E?= Message-ID: http://hg.python.org/cpython/rev/d3c2d8358f54 changeset: 76246:d3c2d8358f54 parent: 76244:f5f8a7fd881c parent: 76245:9d4109af8f3b user: Antoine Pitrou date: Wed Apr 11 19:38:27 2012 +0200 summary: Improve the threading.Condition docs. files: Doc/library/threading.rst | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -584,12 +584,14 @@ # Produce one item with cv: make_an_item_available() + cv.notify() The ``while`` loop checking for the application's condition is necessary because :meth:`~Condition.wait` can return after an arbitrary long time, -and other threads may have exhausted the available items in between. This -is inherent to multi-threaded programming. The :meth:`~Condition.wait_for` -method can be used to automate the condition checking:: +and the condition which prompted the :meth:`~Condition.notify` call may +no longer hold true. This is inherent to multi-threaded programming. The +:meth:`~Condition.wait_for` method can be used to automate the condition +checking, and eases the computation of timeouts:: # Consume an item with cv: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 19:44:10 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 11 Apr 2012 19:44:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Improve_the_thr?= =?utf8?q?eading=2ECondition_docs=2E?= Message-ID: http://hg.python.org/cpython/rev/9d4109af8f3b changeset: 76245:9d4109af8f3b branch: 3.2 parent: 76242:2776ccf003cc user: Antoine Pitrou date: Wed Apr 11 19:37:56 2012 +0200 summary: Improve the threading.Condition docs. files: Doc/library/threading.rst | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -561,12 +561,14 @@ # Produce one item with cv: make_an_item_available() + cv.notify() The ``while`` loop checking for the application's condition is necessary because :meth:`~Condition.wait` can return after an arbitrary long time, -and other threads may have exhausted the available items in between. This -is inherent to multi-threaded programming. The :meth:`~Condition.wait_for` -method can be used to automate the condition checking:: +and the condition which prompted the :meth:`~Condition.notify` call may +no longer hold true. This is inherent to multi-threaded programming. The +:meth:`~Condition.wait_for` method can be used to automate the condition +checking, and eases the computation of timeouts:: # Consume an item with cv: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 20:37:42 2012 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 11 Apr 2012 20:37:42 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Issue_10484_-_I?= =?utf8?q?ncorporate_improvements_to_CGI_module_-_Suggested_by_Glenn?= Message-ID: http://hg.python.org/cpython/rev/c67efb8ffca4 changeset: 76247:c67efb8ffca4 branch: 2.7 parent: 76225:4d49a2415ced user: Senthil Kumaran date: Thu Apr 12 02:23:23 2012 +0800 summary: Issue 10484 - Incorporate improvements to CGI module - Suggested by Glenn Linderman. Refactor code and tests files: Lib/CGIHTTPServer.py | 51 ++++++++-------- Lib/test/test_httpservers.py | 74 ++++++++++++----------- 2 files changed, 64 insertions(+), 61 deletions(-) diff --git a/Lib/CGIHTTPServer.py b/Lib/CGIHTTPServer.py --- a/Lib/CGIHTTPServer.py +++ b/Lib/CGIHTTPServer.py @@ -84,10 +84,9 @@ path begins with one of the strings in self.cgi_directories (and the next character is a '/' or the end of the string). """ - splitpath = _url_collapse_path_split(self.path) - joined_path = '/'.join(splitpath) - dir_sep = joined_path.find('/', 1) - head, tail = joined_path[:dir_sep], joined_path[dir_sep+1:] + collapsed_path = _url_collapse_path(self.path) + dir_sep = collapsed_path.find('/', 1) + head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:] if head in self.cgi_directories: self.cgi_info = head, tail return True @@ -301,44 +300,46 @@ self.log_message("CGI script exited OK") -# TODO(gregory.p.smith): Move this into an appropriate library. -def _url_collapse_path_split(path): +def _url_collapse_path(path): """ Given a URL path, remove extra '/'s and '.' path elements and collapse - any '..' references. + any '..' references and returns a colllapsed path. Implements something akin to RFC-2396 5.2 step 6 to parse relative paths. + The utility of this function is limited to is_cgi method and helps + preventing some security attacks. Returns: A tuple of (head, tail) where tail is everything after the final / and head is everything before it. Head will always start with a '/' and, if it contains anything else, never have a trailing '/'. Raises: IndexError if too many '..' occur within the path. + """ # Similar to os.path.split(os.path.normpath(path)) but specific to URL # path semantics rather than local operating system semantics. - path_parts = [] - for part in path.split('/'): - if part == '.': - path_parts.append('') - else: - path_parts.append(part) - # Filter out blank non trailing parts before consuming the '..'. - path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] + path_parts = path.split('/') + head_parts = [] + for part in path_parts[:-1]: + if part == '..': + head_parts.pop() # IndexError if more '..' than prior parts + elif part and part != '.': + head_parts.append( part ) if path_parts: tail_part = path_parts.pop() + if tail_part: + if tail_part == '..': + head_parts.pop() + tail_part = '' + elif tail_part == '.': + tail_part = '' else: tail_part = '' - head_parts = [] - for part in path_parts: - if part == '..': - head_parts.pop() - else: - head_parts.append(part) - if tail_part and tail_part == '..': - head_parts.pop() - tail_part = '' - return ('/' + '/'.join(head_parts), tail_part) + + splitpath = ('/' + '/'.join(head_parts), tail_part) + collapsed_path = "/".join(splitpath) + + return collapsed_path nobody = None diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -4,11 +4,6 @@ Josip Dzolonga, and Michael Otteneder for the 2007/08 GHOP contest. """ -from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer -from SimpleHTTPServer import SimpleHTTPRequestHandler -from CGIHTTPServer import CGIHTTPRequestHandler -import CGIHTTPServer - import os import sys import re @@ -17,12 +12,17 @@ import urllib import httplib import tempfile +import unittest +import CGIHTTPServer -import unittest +from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +from SimpleHTTPServer import SimpleHTTPRequestHandler +from CGIHTTPServer import CGIHTTPRequestHandler from StringIO import StringIO +from test import test_support -from test import test_support + threading = test_support.import_module('threading') @@ -43,7 +43,7 @@ self.end_headers() self.wfile.write(b'Data\r\n') - def log_message(self, format, *args): + def log_message(self, fmt, *args): pass @@ -97,9 +97,9 @@ self.handler = SocketlessRequestHandler() def send_typical_request(self, message): - input = StringIO(message) + input_msg = StringIO(message) output = StringIO() - self.handler.rfile = input + self.handler.rfile = input_msg self.handler.wfile = output self.handler.handle_one_request() output.seek(0) @@ -296,7 +296,7 @@ os.chdir(self.cwd) try: shutil.rmtree(self.tempdir) - except: + except OSError: pass finally: BaseTestCase.tearDown(self) @@ -418,42 +418,44 @@ finally: BaseTestCase.tearDown(self) - def test_url_collapse_path_split(self): + def test_url_collapse_path(self): # verify tail is the last portion and head is the rest on proper urls test_vectors = { - '': ('/', ''), + '': '//', '..': IndexError, '/.//..': IndexError, - '/': ('/', ''), - '//': ('/', ''), - '/\\': ('/', '\\'), - '/.//': ('/', ''), - 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - 'a': ('/', 'a'), - '/a': ('/', 'a'), - '//a': ('/', 'a'), - './a': ('/', 'a'), - './C:/': ('/C:', ''), - '/a/b': ('/a', 'b'), - '/a/b/': ('/a/b', ''), - '/a/b/c/..': ('/a/b', ''), - '/a/b/c/../d': ('/a/b', 'd'), - '/a/b/c/../d/e/../f': ('/a/b/d', 'f'), - '/a/b/c/../d/e/../../f': ('/a/b', 'f'), - '/a/b/c/../d/e/.././././..//f': ('/a/b', 'f'), + '/': '//', + '//': '//', + '/\\': '//\\', + '/.//': '//', + 'cgi-bin/file1.py': '/cgi-bin/file1.py', + '/cgi-bin/file1.py': '/cgi-bin/file1.py', + 'a': '//a', + '/a': '//a', + '//a': '//a', + './a': '//a', + './C:/': '/C:/', + '/a/b': '/a/b', + '/a/b/': '/a/b/', + '/a/b/.': '/a/b/', + '/a/b/c/..': '/a/b/', + '/a/b/c/../d': '/a/b/d', + '/a/b/c/../d/e/../f': '/a/b/d/f', + '/a/b/c/../d/e/../../f': '/a/b/f', + '/a/b/c/../d/e/.././././..//f': '/a/b/f', '../a/b/c/../d/e/.././././..//f': IndexError, - '/a/b/c/../d/e/../../../f': ('/a', 'f'), - '/a/b/c/../d/e/../../../../f': ('/', 'f'), + '/a/b/c/../d/e/../../../f': '/a/f', + '/a/b/c/../d/e/../../../../f': '//f', '/a/b/c/../d/e/../../../../../f': IndexError, - '/a/b/c/../d/e/../../../../f/..': ('/', ''), + '/a/b/c/../d/e/../../../../f/..': '//', + '/a/b/c/../d/e/../../../../f/../.': '//', } for path, expected in test_vectors.iteritems(): if isinstance(expected, type) and issubclass(expected, Exception): self.assertRaises(expected, - CGIHTTPServer._url_collapse_path_split, path) + CGIHTTPServer._url_collapse_path, path) else: - actual = CGIHTTPServer._url_collapse_path_split(path) + actual = CGIHTTPServer._url_collapse_path(path) self.assertEqual(expected, actual, msg='path = %r\nGot: %r\nWanted: %r' % (path, actual, expected)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 20:37:45 2012 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 11 Apr 2012 20:37:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_3=2E2_-_Issue_1?= =?utf8?q?0484_-_Incorporate_improvements_to_CGI_module_-_Suggested_by_Gle?= =?utf8?q?nn?= Message-ID: http://hg.python.org/cpython/rev/fc001124a3ee changeset: 76248:fc001124a3ee branch: 3.2 parent: 76245:9d4109af8f3b user: Senthil Kumaran date: Thu Apr 12 02:34:32 2012 +0800 summary: 3.2 - Issue 10484 - Incorporate improvements to CGI module - Suggested by Glenn Linderman. Refactor code and tests files: Lib/http/server.py | 54 ++++++++++++----------- Lib/test/test_httpservers.py | 53 ++++++++++++----------- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -825,44 +825,47 @@ # Utilities for CGIHTTPRequestHandler -# TODO(gregory.p.smith): Move this into an appropriate library. -def _url_collapse_path_split(path): +def _url_collapse_path(path): """ Given a URL path, remove extra '/'s and '.' path elements and collapse - any '..' references. + any '..' references and returns a colllapsed path. Implements something akin to RFC-2396 5.2 step 6 to parse relative paths. + The utility of this function is limited to is_cgi method and helps + preventing some security attacks. Returns: A tuple of (head, tail) where tail is everything after the final / and head is everything before it. Head will always start with a '/' and, if it contains anything else, never have a trailing '/'. Raises: IndexError if too many '..' occur within the path. + """ # Similar to os.path.split(os.path.normpath(path)) but specific to URL # path semantics rather than local operating system semantics. - path_parts = [] - for part in path.split('/'): - if part == '.': - path_parts.append('') - else: - path_parts.append(part) - # Filter out blank non trailing parts before consuming the '..'. - path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] + path_parts = path.split('/') + head_parts = [] + for part in path_parts[:-1]: + if part == '..': + head_parts.pop() # IndexError if more '..' than prior parts + elif part and part != '.': + head_parts.append( part ) if path_parts: tail_part = path_parts.pop() + if tail_part: + if tail_part == '..': + head_parts.pop() + tail_part = '' + elif tail_part == '.': + tail_part = '' else: tail_part = '' - head_parts = [] - for part in path_parts: - if part == '..': - head_parts.pop() - else: - head_parts.append(part) - if tail_part and tail_part == '..': - head_parts.pop() - tail_part = '' - return ('/' + '/'.join(head_parts), tail_part) + + splitpath = ('/' + '/'.join(head_parts), tail_part) + collapsed_path = "/".join(splitpath) + + return collapsed_path + nobody = None @@ -943,16 +946,15 @@ (and the next character is a '/' or the end of the string). """ - - splitpath = _url_collapse_path_split(self.path) - joined_path = '/'.join(splitpath) - dir_sep = joined_path.find('/',1) - head, tail = joined_path[:dir_sep], joined_path[dir_sep+1:] + collapsed_path = _url_collapse_path(self.path) + dir_sep = collapsed_path.find('/', 1) + head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:] if head in self.cgi_directories: self.cgi_info = head, tail return True return False + cgi_directories = ['/cgi-bin', '/htbin'] def is_executable(self, path): diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -366,41 +366,44 @@ finally: BaseTestCase.tearDown(self) - def test_url_collapse_path_split(self): + def test_url_collapse_path(self): + # verify tail is the last portion and head is the rest on proper urls test_vectors = { - '': ('/', ''), + '': '//', '..': IndexError, '/.//..': IndexError, - '/': ('/', ''), - '//': ('/', ''), - '/\\': ('/', '\\'), - '/.//': ('/', ''), - 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - 'a': ('/', 'a'), - '/a': ('/', 'a'), - '//a': ('/', 'a'), - './a': ('/', 'a'), - './C:/': ('/C:', ''), - '/a/b': ('/a', 'b'), - '/a/b/': ('/a/b', ''), - '/a/b/c/..': ('/a/b', ''), - '/a/b/c/../d': ('/a/b', 'd'), - '/a/b/c/../d/e/../f': ('/a/b/d', 'f'), - '/a/b/c/../d/e/../../f': ('/a/b', 'f'), - '/a/b/c/../d/e/.././././..//f': ('/a/b', 'f'), + '/': '//', + '//': '//', + '/\\': '//\\', + '/.//': '//', + 'cgi-bin/file1.py': '/cgi-bin/file1.py', + '/cgi-bin/file1.py': '/cgi-bin/file1.py', + 'a': '//a', + '/a': '//a', + '//a': '//a', + './a': '//a', + './C:/': '/C:/', + '/a/b': '/a/b', + '/a/b/': '/a/b/', + '/a/b/.': '/a/b/', + '/a/b/c/..': '/a/b/', + '/a/b/c/../d': '/a/b/d', + '/a/b/c/../d/e/../f': '/a/b/d/f', + '/a/b/c/../d/e/../../f': '/a/b/f', + '/a/b/c/../d/e/.././././..//f': '/a/b/f', '../a/b/c/../d/e/.././././..//f': IndexError, - '/a/b/c/../d/e/../../../f': ('/a', 'f'), - '/a/b/c/../d/e/../../../../f': ('/', 'f'), + '/a/b/c/../d/e/../../../f': '/a/f', + '/a/b/c/../d/e/../../../../f': '//f', '/a/b/c/../d/e/../../../../../f': IndexError, - '/a/b/c/../d/e/../../../../f/..': ('/', ''), + '/a/b/c/../d/e/../../../../f/..': '//', + '/a/b/c/../d/e/../../../../f/../.': '//', } for path, expected in test_vectors.items(): if isinstance(expected, type) and issubclass(expected, Exception): self.assertRaises(expected, - server._url_collapse_path_split, path) + server._url_collapse_path, path) else: - actual = server._url_collapse_path_split(path) + actual = server._url_collapse_path(path) self.assertEqual(expected, actual, msg='path = %r\nGot: %r\nWanted: %r' % (path, actual, expected)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 20:37:46 2012 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 11 Apr 2012 20:37:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_to_default_-_Issue_10484_-_Incorporate_improvements_to?= =?utf8?q?_CGI_module_-?= Message-ID: http://hg.python.org/cpython/rev/23f648d7053b changeset: 76249:23f648d7053b parent: 76246:d3c2d8358f54 parent: 76248:fc001124a3ee user: Senthil Kumaran date: Thu Apr 12 02:37:11 2012 +0800 summary: merge to default - Issue 10484 - Incorporate improvements to CGI module - Suggested by Glenn Linderman. Refactor code and tests files: Lib/http/server.py | 54 ++++++++++++----------- Lib/test/test_httpservers.py | 53 ++++++++++++----------- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -840,44 +840,47 @@ # Utilities for CGIHTTPRequestHandler -# TODO(gregory.p.smith): Move this into an appropriate library. -def _url_collapse_path_split(path): +def _url_collapse_path(path): """ Given a URL path, remove extra '/'s and '.' path elements and collapse - any '..' references. + any '..' references and returns a colllapsed path. Implements something akin to RFC-2396 5.2 step 6 to parse relative paths. + The utility of this function is limited to is_cgi method and helps + preventing some security attacks. Returns: A tuple of (head, tail) where tail is everything after the final / and head is everything before it. Head will always start with a '/' and, if it contains anything else, never have a trailing '/'. Raises: IndexError if too many '..' occur within the path. + """ # Similar to os.path.split(os.path.normpath(path)) but specific to URL # path semantics rather than local operating system semantics. - path_parts = [] - for part in path.split('/'): - if part == '.': - path_parts.append('') - else: - path_parts.append(part) - # Filter out blank non trailing parts before consuming the '..'. - path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] + path_parts = path.split('/') + head_parts = [] + for part in path_parts[:-1]: + if part == '..': + head_parts.pop() # IndexError if more '..' than prior parts + elif part and part != '.': + head_parts.append( part ) if path_parts: tail_part = path_parts.pop() + if tail_part: + if tail_part == '..': + head_parts.pop() + tail_part = '' + elif tail_part == '.': + tail_part = '' else: tail_part = '' - head_parts = [] - for part in path_parts: - if part == '..': - head_parts.pop() - else: - head_parts.append(part) - if tail_part and tail_part == '..': - head_parts.pop() - tail_part = '' - return ('/' + '/'.join(head_parts), tail_part) + + splitpath = ('/' + '/'.join(head_parts), tail_part) + collapsed_path = "/".join(splitpath) + + return collapsed_path + nobody = None @@ -954,16 +957,15 @@ (and the next character is a '/' or the end of the string). """ - - splitpath = _url_collapse_path_split(self.path) - joined_path = '/'.join(splitpath) - dir_sep = joined_path.find('/',1) - head, tail = joined_path[:dir_sep], joined_path[dir_sep+1:] + collapsed_path = _url_collapse_path(self.path) + dir_sep = collapsed_path.find('/', 1) + head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:] if head in self.cgi_directories: self.cgi_info = head, tail return True return False + cgi_directories = ['/cgi-bin', '/htbin'] def is_executable(self, path): diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -366,41 +366,44 @@ finally: BaseTestCase.tearDown(self) - def test_url_collapse_path_split(self): + def test_url_collapse_path(self): + # verify tail is the last portion and head is the rest on proper urls test_vectors = { - '': ('/', ''), + '': '//', '..': IndexError, '/.//..': IndexError, - '/': ('/', ''), - '//': ('/', ''), - '/\\': ('/', '\\'), - '/.//': ('/', ''), - 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - 'a': ('/', 'a'), - '/a': ('/', 'a'), - '//a': ('/', 'a'), - './a': ('/', 'a'), - './C:/': ('/C:', ''), - '/a/b': ('/a', 'b'), - '/a/b/': ('/a/b', ''), - '/a/b/c/..': ('/a/b', ''), - '/a/b/c/../d': ('/a/b', 'd'), - '/a/b/c/../d/e/../f': ('/a/b/d', 'f'), - '/a/b/c/../d/e/../../f': ('/a/b', 'f'), - '/a/b/c/../d/e/.././././..//f': ('/a/b', 'f'), + '/': '//', + '//': '//', + '/\\': '//\\', + '/.//': '//', + 'cgi-bin/file1.py': '/cgi-bin/file1.py', + '/cgi-bin/file1.py': '/cgi-bin/file1.py', + 'a': '//a', + '/a': '//a', + '//a': '//a', + './a': '//a', + './C:/': '/C:/', + '/a/b': '/a/b', + '/a/b/': '/a/b/', + '/a/b/.': '/a/b/', + '/a/b/c/..': '/a/b/', + '/a/b/c/../d': '/a/b/d', + '/a/b/c/../d/e/../f': '/a/b/d/f', + '/a/b/c/../d/e/../../f': '/a/b/f', + '/a/b/c/../d/e/.././././..//f': '/a/b/f', '../a/b/c/../d/e/.././././..//f': IndexError, - '/a/b/c/../d/e/../../../f': ('/a', 'f'), - '/a/b/c/../d/e/../../../../f': ('/', 'f'), + '/a/b/c/../d/e/../../../f': '/a/f', + '/a/b/c/../d/e/../../../../f': '//f', '/a/b/c/../d/e/../../../../../f': IndexError, - '/a/b/c/../d/e/../../../../f/..': ('/', ''), + '/a/b/c/../d/e/../../../../f/..': '//', + '/a/b/c/../d/e/../../../../f/../.': '//', } for path, expected in test_vectors.items(): if isinstance(expected, type) and issubclass(expected, Exception): self.assertRaises(expected, - server._url_collapse_path_split, path) + server._url_collapse_path, path) else: - actual = server._url_collapse_path_split(path) + actual = server._url_collapse_path(path) self.assertEqual(expected, actual, msg='path = %r\nGot: %r\nWanted: %r' % (path, actual, expected)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 21:17:50 2012 From: python-checkins at python.org (r.david.murray) Date: Wed, 11 Apr 2012 21:17:50 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NTA4OiBtYWtl?= =?utf8?q?_gprof2html_script_runnable_under_python3?= Message-ID: http://hg.python.org/cpython/rev/4d603d6782db changeset: 76250:4d603d6782db branch: 3.2 parent: 76248:fc001124a3ee user: R David Murray date: Wed Apr 11 15:16:38 2012 -0400 summary: #14508: make gprof2html script runnable under python3 Not that I haven't tested it to make sure it works, just that it can run against an empty source file. Initial patch by Popa.Claudiu. files: Tools/scripts/gprof2html.py | 12 +++++++----- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Tools/scripts/gprof2html.py b/Tools/scripts/gprof2html.py --- a/Tools/scripts/gprof2html.py +++ b/Tools/scripts/gprof2html.py @@ -19,17 +19,19 @@ """ -def add_escapes(input): - for line in input: - yield cgi.escape(line) +def add_escapes(filename): + with open(filename) as fp: + for line in fp: + yield cgi.escape(line) + def main(): filename = "gprof.out" if sys.argv[1:]: filename = sys.argv[1] outputfilename = filename + ".html" - input = add_escapes(file(filename)) - output = file(outputfilename, "w") + input = add_escapes(filename) + output = open(outputfilename, "w") output.write(header % filename) for line in input: output.write(line) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 21:17:51 2012 From: python-checkins at python.org (r.david.murray) Date: Wed, 11 Apr 2012 21:17:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314508=3A_make_gprof2html_script_runnable_under_python3?= Message-ID: http://hg.python.org/cpython/rev/73fba223c0a5 changeset: 76251:73fba223c0a5 parent: 76249:23f648d7053b parent: 76250:4d603d6782db user: R David Murray date: Wed Apr 11 15:17:37 2012 -0400 summary: #14508: make gprof2html script runnable under python3 Not that I haven't tested it to make sure it works, just that it can run against an empty source file. Initial patch by Popa.Claudiu. Here we also add a test (which uses mock, which is why I didn't check it in on 3.2). files: Lib/test/test_tools.py | 25 ++++++++++++++++++++++++- Tools/scripts/gprof2html.py | 12 +++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -8,6 +8,7 @@ import sys import imp import unittest +from unittest import mock import sysconfig import tempfile from test import support @@ -40,7 +41,7 @@ # added for a script it should be added to the whitelist below. # scripts that have independent tests. - whitelist = ['reindent.py'] + whitelist = ['reindent.py', 'pdeps.py', 'gprof2html'] # scripts that can't be imported without running blacklist = ['make_ctype.py'] # scripts that use windows-only modules @@ -99,6 +100,28 @@ self.pdeps.inverse({'a': []}) +class Gprof2htmlTests(unittest.TestCase): + + def setUp(self): + path = os.path.join(scriptsdir, 'gprof2html.py') + self.gprof = imp.load_source('gprof2html', path) + oldargv = sys.argv + def fixup(): + sys.argv = oldargv + self.addCleanup(fixup) + sys.argv = [] + + def test_gprof(self): + # Issue #14508: this used to fail with an NameError. + with mock.patch.object(self.gprof, 'webbrowser') as wmock, \ + tempfile.TemporaryDirectory() as tmpdir: + fn = os.path.join(tmpdir, 'abc') + open(fn, 'w').close() + sys.argv = ['gprof2html', fn] + self.gprof.main() + self.assertTrue(wmock.open.called) + + def test_main(): support.run_unittest(*[obj for obj in globals().values() if isinstance(obj, type)]) diff --git a/Tools/scripts/gprof2html.py b/Tools/scripts/gprof2html.py --- a/Tools/scripts/gprof2html.py +++ b/Tools/scripts/gprof2html.py @@ -19,17 +19,19 @@ """ -def add_escapes(input): - for line in input: - yield cgi.escape(line) +def add_escapes(filename): + with open(filename) as fp: + for line in fp: + yield cgi.escape(line) + def main(): filename = "gprof.out" if sys.argv[1:]: filename = sys.argv[1] outputfilename = filename + ".html" - input = add_escapes(file(filename)) - output = file(outputfilename, "w") + input = add_escapes(filename) + output = open(outputfilename, "w") output.write(header % filename) for line in input: output.write(line) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 22:12:26 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 11 Apr 2012 22:12:26 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_we_live_in_a_po?= =?utf8?q?st_2=2E7=2E3_world?= Message-ID: http://hg.python.org/cpython/rev/545f8009f01b changeset: 76252:545f8009f01b branch: 2.7 parent: 76202:9649871ef35b user: Benjamin Peterson date: Wed Apr 11 16:09:54 2012 -0400 summary: we live in a post 2.7.3 world files: Include/patchlevel.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -27,7 +27,7 @@ #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.7.3" +#define PY_VERSION "2.7.3+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 22:12:26 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 11 Apr 2012 22:12:26 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/5324c821da95 changeset: 76253:5324c821da95 branch: 2.7 parent: 76252:545f8009f01b parent: 76203:35d95a36afbb user: Benjamin Peterson date: Wed Apr 11 16:10:07 2012 -0400 summary: merge heads files: Doc/library/imp.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -65,7 +65,7 @@ path and the last item in the *description* tuple is :const:`PKG_DIRECTORY`. This function does not handle hierarchical module names (names containing - dots). In order to find *P*.*M*, that is, submodule *M* of package *P*, use + dots). In order to find *P.M*, that is, submodule *M* of package *P*, use :func:`find_module` and :func:`load_module` to find and load package *P*, and then use :func:`find_module` with the *path* argument set to ``P.__path__``. When *P* itself has a dotted name, apply this recipe recursively. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 22:12:27 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 11 Apr 2012 22:12:27 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/5d5573d94988 changeset: 76254:5d5573d94988 branch: 2.7 parent: 76253:5324c821da95 parent: 76247:c67efb8ffca4 user: Benjamin Peterson date: Wed Apr 11 16:12:21 2012 -0400 summary: merge heads files: .hgtags | 1 + Doc/howto/logging.rst | 15 ++++ Doc/library/logging.rst | 16 ++++- Doc/library/re.rst | 24 +++--- Lib/CGIHTTPServer.py | 61 +++++++++---------- Lib/test/test_httpservers.py | 76 ++++++++++++----------- 6 files changed, 110 insertions(+), 83 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -139,6 +139,7 @@ 9f8771e0905277f8b3c2799113a062fda4164995 v2.6.6 caab08cd2b3eb5a6f78479b2513b65d36c754f41 v2.6.8rc1 1d1b7b9fad48bd0dc60dc8a06cca4459ef273127 v2.6.8rc2 +c9910fd022fc842e5578e1bf5a30ba55a37239fc v2.6.8 b4107eb00b4271fb73a9e1b736d4f23460950778 v2.7a1 adc85ebc7271cc22e24e816782bb2b8d7fa3a6b3 v2.7a2 4180557b7a9bb9dd5341a18af199f843f199e46e v2.7a3 diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -642,6 +642,21 @@ code approach, mainly separation of configuration and code and the ability of noncoders to easily modify the logging properties. +.. warning:: The :func:`fileConfig` function takes a default parameter, + ``disable_existing_loggers``, which defaults to ``True`` for reasons of + backward compatibility. This may or may not be what you want, since it + will cause any loggers existing before the :func:`fileConfig` call to + be disabled unless they (or an ancestor) are explicitly named in the + configuration. Please refer to the reference documentation for more + information, and specify ``False`` for this parameter if you wish. + + The dictionary passed to :func:`dictConfig` can also specify a Boolean + value with key ``disable_existing_loggers``, which if not specified + explicitly in the dictionary also defaults to being interpreted as + ``True``. This leads to the logger-disabling behaviour described above, + which may not be what you want - in which case, provide the key + explicitly with a value of ``False``. + .. currentmodule:: logging Note that the class names referenced in config files need to be either relative diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -51,9 +51,21 @@ Logger Objects -------------- -Loggers have the following attributes and methods. Note that Loggers are never +Loggers have the following attributes and methods. Note that Loggers are never instantiated directly, but always through the module-level function -``logging.getLogger(name)``. +``logging.getLogger(name)``. Multiple calls to :func:`getLogger` with the same +name will always return a reference to the same Logger object. + +The ``name`` is potentially a period-separated hierarchical value, like +``foo.bar.baz`` (though it could also be just plain ``foo``, for example). +Loggers that are further down in the hierarchical list are children of loggers +higher up in the list. For example, given a logger with a name of ``foo``, +loggers with names of ``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all +descendants of ``foo``. The logger name hierarchy is analogous to the Python +package hierarchy, and identical to it if you organise your loggers on a +per-module basis using the recommended construction +``logging.getLogger(__name__)``. That's because in a module, ``__name__`` +is the module's name in the Python package namespace. .. class:: Logger diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -353,20 +353,20 @@ character properties database. ``\s`` - When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, matches - any whitespace character; this is equivalent to the set ``[ \t\n\r\f\v]``. With - :const:`LOCALE`, it will match this set plus whatever characters are defined as - space for the current locale. If :const:`UNICODE` is set, this will match the - characters ``[ \t\n\r\f\v]`` plus whatever is classified as space in the Unicode - character properties database. + When the :const:`UNICODE` flag is not specified, it matches any whitespace + character, this is equivalent to the set ``[ \t\n\r\f\v]``. The + :const:`LOCALE` flag has no extra effect on matching of the space. + If :const:`UNICODE` is set, this will match the characters ``[ \t\n\r\f\v]`` + plus whatever is classified as space in the Unicode character properties + database. ``\S`` - When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, - matches any non-whitespace character; this is equivalent to the set ``[^ - \t\n\r\f\v]`` With :const:`LOCALE`, it will match the above set plus any - non-space character in the current locale. If :const:`UNICODE` is set, the - above set ``[^ \t\n\r\f\v]`` plus the characters not marked as space in the - Unicode character properties database. + When the :const:`UNICODE` flags is not specified, matches any non-whitespace + character; this is equivalent to the set ``[^ \t\n\r\f\v]`` The + :const:`LOCALE` flag has no extra effect on non-whitespace match. If + :const:`UNICODE` is set, then any character not marked as space in the + Unicode character properties database is matched. + ``\w`` When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, matches diff --git a/Lib/CGIHTTPServer.py b/Lib/CGIHTTPServer.py --- a/Lib/CGIHTTPServer.py +++ b/Lib/CGIHTTPServer.py @@ -84,9 +84,11 @@ path begins with one of the strings in self.cgi_directories (and the next character is a '/' or the end of the string). """ - splitpath = _url_collapse_path_split(self.path) - if splitpath[0] in self.cgi_directories: - self.cgi_info = splitpath + collapsed_path = _url_collapse_path(self.path) + dir_sep = collapsed_path.find('/', 1) + head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:] + if head in self.cgi_directories: + self.cgi_info = head, tail return True return False @@ -298,51 +300,46 @@ self.log_message("CGI script exited OK") -# TODO(gregory.p.smith): Move this into an appropriate library. -def _url_collapse_path_split(path): +def _url_collapse_path(path): """ Given a URL path, remove extra '/'s and '.' path elements and collapse - any '..' references. + any '..' references and returns a colllapsed path. Implements something akin to RFC-2396 5.2 step 6 to parse relative paths. + The utility of this function is limited to is_cgi method and helps + preventing some security attacks. Returns: A tuple of (head, tail) where tail is everything after the final / and head is everything before it. Head will always start with a '/' and, if it contains anything else, never have a trailing '/'. Raises: IndexError if too many '..' occur within the path. + """ # Similar to os.path.split(os.path.normpath(path)) but specific to URL # path semantics rather than local operating system semantics. - path_parts = [] - for part in path.split('/'): - if part == '.': - path_parts.append('') - else: - path_parts.append(part) - # Filter out blank non trailing parts before consuming the '..'. - path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] + path_parts = path.split('/') + head_parts = [] + for part in path_parts[:-1]: + if part == '..': + head_parts.pop() # IndexError if more '..' than prior parts + elif part and part != '.': + head_parts.append( part ) if path_parts: - # Special case for CGI's for PATH_INFO - if path.startswith('/cgi-bin') or path.startswith('/htbin'): - tail_part = [] - while path_parts[-1] not in ('cgi-bin','htbin'): - tail_part.insert(0,path_parts.pop()) - tail_part = "/".join(tail_part) - else: - tail_part = path_parts.pop() + tail_part = path_parts.pop() + if tail_part: + if tail_part == '..': + head_parts.pop() + tail_part = '' + elif tail_part == '.': + tail_part = '' else: tail_part = '' - head_parts = [] - for part in path_parts: - if part == '..': - head_parts.pop() - else: - head_parts.append(part) - if tail_part and tail_part == '..': - head_parts.pop() - tail_part = '' - return ('/' + '/'.join(head_parts), tail_part) + + splitpath = ('/' + '/'.join(head_parts), tail_part) + collapsed_path = "/".join(splitpath) + + return collapsed_path nobody = None diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -4,11 +4,6 @@ Josip Dzolonga, and Michael Otteneder for the 2007/08 GHOP contest. """ -from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer -from SimpleHTTPServer import SimpleHTTPRequestHandler -from CGIHTTPServer import CGIHTTPRequestHandler -import CGIHTTPServer - import os import sys import re @@ -17,12 +12,17 @@ import urllib import httplib import tempfile +import unittest +import CGIHTTPServer -import unittest +from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +from SimpleHTTPServer import SimpleHTTPRequestHandler +from CGIHTTPServer import CGIHTTPRequestHandler from StringIO import StringIO +from test import test_support -from test import test_support + threading = test_support.import_module('threading') @@ -43,7 +43,7 @@ self.end_headers() self.wfile.write(b'Data\r\n') - def log_message(self, format, *args): + def log_message(self, fmt, *args): pass @@ -97,9 +97,9 @@ self.handler = SocketlessRequestHandler() def send_typical_request(self, message): - input = StringIO(message) + input_msg = StringIO(message) output = StringIO() - self.handler.rfile = input + self.handler.rfile = input_msg self.handler.wfile = output self.handler.handle_one_request() output.seek(0) @@ -296,7 +296,7 @@ os.chdir(self.cwd) try: shutil.rmtree(self.tempdir) - except: + except OSError: pass finally: BaseTestCase.tearDown(self) @@ -418,42 +418,44 @@ finally: BaseTestCase.tearDown(self) - def test_url_collapse_path_split(self): + def test_url_collapse_path(self): + # verify tail is the last portion and head is the rest on proper urls test_vectors = { - '': ('/', ''), + '': '//', '..': IndexError, '/.//..': IndexError, - '/': ('/', ''), - '//': ('/', ''), - '/\\': ('/', '\\'), - '/.//': ('/', ''), - 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), - '/cgi-bin/file1.py/PATH-INFO': ('/cgi-bin', 'file1.py/PATH-INFO'), - 'a': ('/', 'a'), - '/a': ('/', 'a'), - '//a': ('/', 'a'), - './a': ('/', 'a'), - './C:/': ('/C:', ''), - '/a/b': ('/a', 'b'), - '/a/b/': ('/a/b', ''), - '/a/b/c/..': ('/a/b', ''), - '/a/b/c/../d': ('/a/b', 'd'), - '/a/b/c/../d/e/../f': ('/a/b/d', 'f'), - '/a/b/c/../d/e/../../f': ('/a/b', 'f'), - '/a/b/c/../d/e/.././././..//f': ('/a/b', 'f'), + '/': '//', + '//': '//', + '/\\': '//\\', + '/.//': '//', + 'cgi-bin/file1.py': '/cgi-bin/file1.py', + '/cgi-bin/file1.py': '/cgi-bin/file1.py', + 'a': '//a', + '/a': '//a', + '//a': '//a', + './a': '//a', + './C:/': '/C:/', + '/a/b': '/a/b', + '/a/b/': '/a/b/', + '/a/b/.': '/a/b/', + '/a/b/c/..': '/a/b/', + '/a/b/c/../d': '/a/b/d', + '/a/b/c/../d/e/../f': '/a/b/d/f', + '/a/b/c/../d/e/../../f': '/a/b/f', + '/a/b/c/../d/e/.././././..//f': '/a/b/f', '../a/b/c/../d/e/.././././..//f': IndexError, - '/a/b/c/../d/e/../../../f': ('/a', 'f'), - '/a/b/c/../d/e/../../../../f': ('/', 'f'), + '/a/b/c/../d/e/../../../f': '/a/f', + '/a/b/c/../d/e/../../../../f': '//f', '/a/b/c/../d/e/../../../../../f': IndexError, - '/a/b/c/../d/e/../../../../f/..': ('/', ''), + '/a/b/c/../d/e/../../../../f/..': '//', + '/a/b/c/../d/e/../../../../f/../.': '//', } for path, expected in test_vectors.iteritems(): if isinstance(expected, type) and issubclass(expected, Exception): self.assertRaises(expected, - CGIHTTPServer._url_collapse_path_split, path) + CGIHTTPServer._url_collapse_path, path) else: - actual = CGIHTTPServer._url_collapse_path_split(path) + actual = CGIHTTPServer._url_collapse_path(path) self.assertEqual(expected, actual, msg='path = %r\nGot: %r\nWanted: %r' % (path, actual, expected)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 22:48:47 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 11 Apr 2012 22:48:47 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_a_table_with_pe?= =?utf8?q?rformances_of_TSC=2C_ACPI_PM_and_HPET_clocks?= Message-ID: http://hg.python.org/peps/rev/4387c185deb7 changeset: 4219:4387c185deb7 user: Victor Stinner date: Wed Apr 11 22:48:14 2012 +0200 summary: PEP 418: Add a table with performances of TSC, ACPI PM and HPET clocks files: pep-0418.txt | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -299,7 +299,7 @@ frequency. Multiple cores having different TSC values. Hibernation of system will reset TSC value. The RDTSC instruction can be used to read this counter. CPU frequency scaling for power saving. -* ACPI PMTMR (power management timer): ACPI 24-bit timer with a frequency +* ACPI PMTMR (Power Management TiMeR): ACPI 24-bit timer with a frequency of 3.5 MHz (3,579,545 Hz). HPET can cause around 3 seconds of drift per day. * Cyclone: The Cyclone timer uses a 32-bit counter on IBM Extended X-Architecture (EXA) chipsets which include computers that use the @@ -310,6 +310,30 @@ * RTC (Real-time clock). Most RTCs use a crystal oscillator with a frequency of 32,768 Hz +Reading an hardware clock has a cost. The following table compares the +performance of different hardware clocks on Linux 3.3 with Intel Core i7-2600 +at 3.40GHz (8 cores). + +======================== ====== ======= ====== +Function TSC ACPI PM HPET +======================== ====== ======= ====== +time() 2 ns 2 ns 2 ns +CLOCK_REALTIME_COARSE 10 ns 10 ns 10 ns +CLOCK_MONOTONIC_COARSE 12 ns 13 ns 12 ns +CLOCK_THREAD_CPUTIME_ID 134 ns 135 ns 135 ns +CLOCK_PROCESS_CPUTIME_ID 127 ns 129 ns 129 ns +clock() 146 ns 146 ns 143 ns +gettimeofday() 23 ns 726 ns 637 ns +CLOCK_MONOTONIC_RAW 31 ns 716 ns 607 ns +CLOCK_REALTIME 27 ns 707 ns 629 ns +CLOCK_MONOTONIC 27 ns 723 ns 635 ns +======================== ====== ======= ====== + +Each function was called 10,000,000 times and CLOCK_MONOTONIC was used to get +the time before and after. The benchmark was run 5 times to keep the minimum +time. + + NTP adjustment ============== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 11 22:49:56 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 11 Apr 2012 22:49:56 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4xKTogYWZ0ZXIgMy4xLjU=?= Message-ID: http://hg.python.org/cpython/rev/5a6fa1b8767f changeset: 76255:5a6fa1b8767f branch: 3.1 parent: 76191:64bb1d258322 user: Benjamin Peterson date: Wed Apr 11 16:46:54 2012 -0400 summary: after 3.1.5 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 0 /* Version as a string */ -#define PY_VERSION "3.1.5" +#define PY_VERSION "3.1.5+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty 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.1.6? +=========================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.1.5? =========================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 22:49:57 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 11 Apr 2012 22:49:57 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMy4xIC0+IDMuMik6?= =?utf8?q?_merge_3=2E1_=28null=29?= Message-ID: http://hg.python.org/cpython/rev/19fd998d1e15 changeset: 76256:19fd998d1e15 branch: 3.2 parent: 76250:4d603d6782db parent: 76255:5a6fa1b8767f user: Benjamin Peterson date: Wed Apr 11 16:48:30 2012 -0400 summary: merge 3.1 (null) files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 11 22:49:58 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 11 Apr 2012 22:49:58 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?b?OiBtZXJnZSAzLjIgKG51bGwp?= Message-ID: http://hg.python.org/cpython/rev/91f161335689 changeset: 76257:91f161335689 parent: 76251:73fba223c0a5 parent: 76256:19fd998d1e15 user: Benjamin Peterson date: Wed Apr 11 16:49:40 2012 -0400 summary: merge 3.2 (null) files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 00:19:49 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 00:19:49 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_another_benchmark_o?= =?utf8?q?n_FreeBSD?= Message-ID: http://hg.python.org/peps/rev/0f66f87b0f86 changeset: 4220:0f66f87b0f86 user: Victor Stinner date: Thu Apr 12 00:19:16 2012 +0200 summary: PEP 418: another benchmark on FreeBSD Add also more info on FreeBSD timecounters files: pep-0418.txt | 68 +++++++++++++++++++++++++++++++++++++-- 1 files changed, 63 insertions(+), 5 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -333,6 +333,33 @@ the time before and after. The benchmark was run 5 times to keep the minimum time. +FreeBSD 8.0 in kvm with hardware virtualization: + +======================== ====== ========= ======= ======= +Function TSC ACPI-Safe HPET i8254 +======================== ====== ========= ======= ======= +time() 191 ns 188 ns 189 ns 188 ns +CLOCK_SECOND 187 ns 184 ns 187 ns 183 ns +CLOCK_REALTIME_FAST 189 ns 180 ns 187 ns 190 ns +CLOCK_UPTIME_FAST 191 ns 185 ns 186 ns 196 ns +CLOCK_MONOTONIC_FAST 188 ns 187 ns 188 ns 189 ns +CLOCK_THREAD_CPUTIME_ID 208 ns 206 ns 207 ns 220 ns +CLOCK_VIRTUAL 280 ns 279 ns 283 ns 296 ns +CLOCK_PROF 289 ns 280 ns 282 ns 286 ns +clock() 342 ns 340 ns 337 ns 344 ns +CLOCK_UPTIME_PRECISE 197 ns 10380 ns 4402 ns 4097 ns +CLOCK_REALTIME 196 ns 10376 ns 4337 ns 4054 ns +CLOCK_MONOTONIC_PRECISE 198 ns 10493 ns 4413 ns 3958 ns +CLOCK_UPTIME 197 ns 10523 ns 4458 ns 4058 ns +gettimeofday() 202 ns 10524 ns 4186 ns 3962 ns +CLOCK_REALTIME_PRECISE 197 ns 10599 ns 4394 ns 4060 ns +CLOCK_MONOTONIC 201 ns 10766 ns 4498 ns 3943 ns +======================== ====== ========= ======= ======= + +Each function was called 100,000 times and CLOCK_MONOTONIC was used to get +the time before and after. The benchmark was run 5 times to keep the minimum +time. + NTP adjustment @@ -827,16 +854,17 @@ so usually higher than 1 GHz. Its priority is 300 by default, but falls to 0 if the processor frequency changes and the counter becomes unstable. -* HPET: An HPET chip consists of a 64-bit up-counter (main counter) - counting at least at 10 MHz and a set of up to 256 comparators (at - least 3). Each HPET can have up to 32 timers. +* HPET: An High Precision Event Timer (HPET) chip consists of a 64-bit + up-counter (main counter) counting at least at 10 MHz and a set of up to 256 + comparators (at least 3). Each HPET can have up to 32 timers. HPET can + cause around 3 seconds of drift per day. * PIT (programmable interrupt timer): Intel 8253/8254 chipsets with a configurable frequency in range 18.2 Hz - 1.2 MHz. Linux uses the frequency 1,193,181.8 Hz. It is a 16-bit counter. * PMTMR (power management timer): ACPI 24-bit timer with a frequency of 3.5 MHz (3,579,545 Hz). Its priority is 200 by default, but changes to 110 if the chipset is broken and need a software - workaround. HPET can cause around 3 seconds of drift per day. + workaround. * Cyclone: The Cyclone timer uses a 32-bit counter on IBM Extended X-Architecture (EXA) chipsets which include computers that use the IBM "Summit" series chipsets (ex: x440). This is available in IA32 @@ -859,11 +887,38 @@ FreeBSD timers -------------- -The sysctl program can be used to change the timecounter. For example:: +kern.timecounter.choice list available hardward clocks with their priority. +The sysctl program can be used to change the timecounter. Example:: + # dmesg|grep Timecounter + Timecounter "i8254" frequency 1193182 Hz quality 0 + Timecounter "ACPI-safe" frequency 3579545 Hz quality 850 + Timecounter "HPET" frequency 100000000 Hz quality 900 + Timecounter "TSC" frequency 3411154800 Hz quality 800 + Timecounters tick every 10.000 msec + # sysctl kern.timecounter.choice + kern.timecounter.choice: TSC(800) HPET(900) ACPI-safe(850) i8254(0) dummy(-1000000) # sysctl kern.timecounter.hardware="ACPI-fast" kern.timecounter.hardware: HPET -> ACPI-fast +Available clocks: + + * "TSC": Time Stamp Counter of the procesor + * "HPET": High Precision Event Timer + * "ACPI-fast": ACPI Power Management timer (fast mode) + * "ACPI-safe": ACPI Power Management timer (safe mode) + * "i8254": PIT with Intel 8254 chipset + +The `commit 222222 +`_ (May 2011) +decreased ACPI-fast timecounter quality to 900 and increased HPET timecounter +quality to 950: "HPET on modern platforms usually have better resolution and +lower latency than ACPI timer". + +Read `Timecounters: Efficient and precise timekeeping in SMP kernels +`_ by Matthew Wilson, May 01, 2003 +* `Counter Availability and Characteristics for Feed-forward Based Synchronization + `_ + by Timothy Broomhead, Julien Ridoux, Darryl Veitch (2009) * System Management Interrupt (SMI) issues: * `System Management Interrupt Free Hardware -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 00:33:19 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 00:33:19 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_bench=5Ftime=2E?= =?utf8?q?c?= Message-ID: http://hg.python.org/peps/rev/153b3f58f371 changeset: 4221:153b3f58f371 user: Victor Stinner date: Thu Apr 12 00:32:44 2012 +0200 summary: PEP 418: Add bench_time.c files: pep-0418/bench_time.c | 162 ++++++++++++++++++++++++++++++ 1 files changed, 162 insertions(+), 0 deletions(-) diff --git a/pep-0418/bench_time.c b/pep-0418/bench_time.c new file mode 100644 --- /dev/null +++ b/pep-0418/bench_time.c @@ -0,0 +1,162 @@ +/* + * Benchmark program written for the PEP 418. + * + * gcc bench_time.c -O3 -lrt -o bench_time && ./bench_time + */ + +#include +#include +#include + +#define NRUN 5 +#define NLOOP 1000000 +#define UNROLL(expr) \ + expr; expr; expr; expr; expr; expr; expr; expr; expr; expr +#define NUNROLL 10 + +typedef struct { + const char *name; + clockid_t identifier; +} CLOCK; + +CLOCK clocks[] = { +#ifdef CLOCK_REALTIME_COARSE + {"CLOCK_REALTIME_COARSE", CLOCK_REALTIME_COARSE}, +#endif +#ifdef CLOCK_MONOTONIC_COARSE + {"CLOCK_MONOTONIC_COARSE", CLOCK_MONOTONIC_COARSE}, +#endif +#ifdef CLOCK_THREAD_CPUTIME_ID + {"CLOCK_THREAD_CPUTIME_ID", CLOCK_THREAD_CPUTIME_ID}, +#endif +#ifdef CLOCK_PROCESS_CPUTIME_ID + {"CLOCK_PROCESS_CPUTIME_ID", CLOCK_PROCESS_CPUTIME_ID}, +#endif +#ifdef CLOCK_MONOTONIC_RAW + {"CLOCK_MONOTONIC_RAW", CLOCK_MONOTONIC_RAW}, +#endif +#ifdef CLOCK_VIRTUAL + {"CLOCK_VIRTUAL", CLOCK_VIRTUAL}, +#endif +#ifdef CLOCK_UPTIME_FAST + {"CLOCK_UPTIME_FAST", CLOCK_UPTIME_FAST}, +#endif +#ifdef CLOCK_UPTIME_PRECISE + {"CLOCK_UPTIME_PRECISE", CLOCK_UPTIME_PRECISE}, +#endif +#ifdef CLOCK_UPTIME + {"CLOCK_UPTIME", CLOCK_UPTIME}, +#endif +#ifdef CLOCK_MONOTONIC_FAST + {"CLOCK_MONOTONIC_FAST", CLOCK_MONOTONIC_FAST}, +#endif +#ifdef CLOCK_MONOTONIC_PRECISE + {"CLOCK_MONOTONIC_PRECISE", CLOCK_MONOTONIC_PRECISE}, +#endif +#ifdef CLOCK_REALTIME_FAST + {"CLOCK_REALTIME_FAST", CLOCK_REALTIME_FAST}, +#endif +#ifdef CLOCK_REALTIME_PRECISE + {"CLOCK_REALTIME_PRECISE", CLOCK_REALTIME_PRECISE}, +#endif +#ifdef CLOCK_SECOND + {"CLOCK_SECOND", CLOCK_SECOND}, +#endif +#ifdef CLOCK_PROF + {"CLOCK_PROF", CLOCK_PROF}, +#endif + {"CLOCK_MONOTONIC", CLOCK_MONOTONIC}, + {"CLOCK_REALTIME", CLOCK_REALTIME} +}; +#define NCLOCKS (sizeof(clocks) / sizeof(clocks[0])) + +void bench_clock_gettime(clockid_t clkid) +{ + unsigned long loop; + struct timespec tmpspec; + + for (loop=0; loop= before.tv_nsec) + dt += (after.tv_nsec - before.tv_nsec) * 1e-9; + else + { + dt -= 1.0; + dt += (before.tv_nsec - after.tv_nsec) * 1e-9; + } + dt *= (double)1e9 / NLOOP / NUNROLL; + + if (best != 0.0) { + if (dt < best) + best = dt; + } + else + best = dt; + } + printf("%s: %.0f ns\n", name, best, NLOOP); +} + +int main() +{ + clockid_t clkid; + int i; + + for (i=0; i http://hg.python.org/peps/rev/4919f7292c33 changeset: 4222:4919f7292c33 user: Victor Stinner date: Thu Apr 12 00:34:32 2012 +0200 summary: PEP 418: Mention the issue #14555 files: pep-0418.txt | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1226,6 +1226,8 @@ `_ * `Issue #14428: Implementation of the PEP 418 `_ +* `Issue #14555: clock_gettime/settime/getres: Add more clock identifiers + `_ Libraries exposing monotonic clocks: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 00:36:36 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 00:36:36 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_syntax_of_a_lin?= =?utf8?q?k?= Message-ID: http://hg.python.org/peps/rev/802809d332b8 changeset: 4223:802809d332b8 user: Victor Stinner date: Thu Apr 12 00:36:02 2012 +0200 summary: PEP 418: Fix syntax of a link files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -916,7 +916,7 @@ lower latency than ACPI timer". Read `Timecounters: Efficient and precise timekeeping in SMP kernels -`_ by Poul-Henning Kamp (2002) for the FreeBSD Project. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 00:39:56 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 00:39:56 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Replace_accuracy_wi?= =?utf8?q?th_precision?= Message-ID: http://hg.python.org/peps/rev/a86b09fffca8 changeset: 4224:a86b09fffca8 user: Victor Stinner date: Thu Apr 12 00:39:22 2012 +0200 summary: PEP 418: Replace accuracy with precision files: pep-0418.txt | 54 ++++++++++++++++++++-------------------- 1 files changed, 27 insertions(+), 27 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -127,7 +127,7 @@ On Windows, QueryPerformanceCounter() is not used even though it has a better -accuracy than GetTickCount(). It is not reliable and has too many issues. +precision than GetTickCount(). It is not reliable and has too many issues. .. note:: @@ -242,7 +242,7 @@ * Optional keys: - * "accuracy" (float): accuracy in seconds of the clock + * "precision" (float): precision in seconds of the clock * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a NTP daemon) @@ -258,12 +258,12 @@ structure which has two integer fields, tv_sec and tv_nsec, so the resolution is 1 nanosecond. -Accuracy +Precision -------- -The accuracy is the effective smallest difference between two timestamps of the +The precision is the effective smallest difference between two timestamps of the clock. It does not reflect the stability the clock rate. For example, -QueryPerformanceCounter() has a good accuracy but is known to not have a steady +QueryPerformanceCounter() has a good precision but is known to not have a steady rate. @@ -407,10 +407,10 @@ timeGetTime() 1 ms No Yes ? ========================= ========== =============== ============= =============== -Examples of clock accuracy on x86_64: +Examples of clock precision on x86_64: ========================= ================ =============== -Name Operating system Accuracy +Name Operating system Precision ========================= ================ =============== CLOCK_MONOTONIC_RAW Linux 3.2 1 ns CLOCK_MONOTONIC Linux 3.2 1 ns @@ -422,7 +422,7 @@ GetTickCount Windows Seven 15.6 ms ========================= ================ =============== -For CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW, the accuracy of this table is the +For CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW, the precision of this table is the result of clock_getres(). It looks like Linux does not implement clock_getres() and always return 1 nanosecond. @@ -507,7 +507,7 @@ High-resolution performance counter. It is monotonic. QueryPerformanceFrequency() gives its frequency. -It has a much higher resolution, but has lower long term accuracy than +It has a much higher resolution, but has lower long term precision than GetTickCount() and timeGetTime() clocks. For example, it will drift compared to the low precision clocks. @@ -577,8 +577,8 @@ GetTickCount64() was added to Windows Vista and Windows Server 2008. -The clock resolution is 1 millisecond. Its accuracy is usually around -15 ms. It is possible to improve the accuracy using the `undocumented +The clock resolution is 1 millisecond. Its precision is usually around +15 ms. It is possible to improve the precision using the `undocumented NtSetTimerResolution() function `_. There are applications using this undocumented function, example: @@ -587,7 +587,7 @@ WaitForSingleObject() use the same timer than GetTickCount() with the same resolution. -GetTickCount() has an accuracy of 55 ms on Windows 9x. +GetTickCount() has an precision of 55 ms on Windows 9x. Windows: timeGetTime @@ -662,10 +662,10 @@ time() 1 sec ========================= =============== -Examples of clock accuracy on x86_64: +Examples of clock precision on x86_64: ========================= ================ =============== -Name Operating system Accuracy +Name Operating system Precision ========================= ================ =============== CLOCK_REALTIME Linux 3.2 1 ns CLOCK_REALTIME FreeBSD 8.2 11 ns @@ -674,7 +674,7 @@ GetSystemTimeAsFileTime Windows Seven 15.6 ms ========================= ================ =============== -For CLOCK_REALTIME, the accuracy of this table is the result of clock_getres(). +For CLOCK_REALTIME, the precision of this table is the result of clock_getres(). It looks like Linux does not implement clock_getres() and always return 1 nanosecond. @@ -691,7 +691,7 @@ and time(). The system time resolution can be read using -GetSystemTimeAdjustment(). The accuracy is usually between 1 +GetSystemTimeAdjustment(). The precision is usually between 1 millisecond and 15 milliseconds. Resolution: * GetSystemTimeAsFileTime(): 100 nanoseconds @@ -723,7 +723,7 @@ Process time ------------ -The process time cannot be set. It It is not monotonic: the clocks stop while the +The process time cannot be set. It is not monotonic: the clocks stop while the process is idle. ========================= =============== @@ -734,10 +734,10 @@ clock() \- ========================= =============== -Examples of clock accuracy on x86_64: +Examples of clock precision on x86_64: ========================= ================ =============== -Name Operating system Accuracy +Name Operating system Precision ========================= ================ =============== CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns clock() Linux 3.2 1 ?s @@ -747,10 +747,10 @@ GetProcessTimes() Windows Seven 15.6 ms ========================= ================ =============== -The accuracy of clock() in this table is the result of 1 / CLOCKS_PER_SEC. -For CLOCK_PROCESS_CPUTIME_ID, the accuracy of this table is the result of +The precision of clock() in this table is the result of 1 / CLOCKS_PER_SEC. +For CLOCK_PROCESS_CPUTIME_ID, the precision of this table is the result of clock_getres(). It looks like Linux does not implement clock_getres() and -always return 1 nanosecond. For GetProcessTimes(), the accuracy is read using +always return 1 nanosecond. For GetProcessTimes(), the precision is read using GetSystemTimeAdjustment(). @@ -792,19 +792,19 @@ CLOCK_THREAD_CPUTIME_ID 1 ns ========================= =============== -Examples of clock accuracy on x86_64: +Examples of clock precision on x86_64: ========================= ================ =============== -Name Operating system Accuracy +Name Operating system Precision ========================= ================ =============== CLOCK_THREAD_CPUTIME_ID Linux 3.2 1 ns CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s GetThreadTimes() Windows Seven 15.6 ms ========================= ================ =============== -For CLOCK_THREAD_CPUTIME_ID, the accuracy of this table is the result of +For CLOCK_THREAD_CPUTIME_ID, the precision of this table is the result of clock_getres(). It looks like Linux does not implement clock_getres() and -always return 1 nanosecond. For GetThreadTimes(), the accuracy is read using +always return 1 nanosecond. For GetThreadTimes(), the precision is read using GetSystemTimeAdjustment(). Functions @@ -1016,7 +1016,7 @@ select(nfds, readfds, writefds, exceptfs, timeout). Since Linux 2.6.28, select() uses high-resolution timers to handle the timeout. -A process has a "slack" attribute to configure the accuracy of the timeout, the +A process has a "slack" attribute to configure the precision of the timeout, the default slack is 50 microseconds. Before Linux 2.6.28, timeouts for select() were handled by the main timing subsystem at a jiffy-level resolution. Read also `High- (but not too high-) resolution timeouts -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 00:42:17 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 00:42:17 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_reST_syntax_of_?= =?utf8?q?a_title?= Message-ID: http://hg.python.org/peps/rev/13d249a7d51d changeset: 4225:13d249a7d51d user: Victor Stinner date: Thu Apr 12 00:41:42 2012 +0200 summary: PEP 418: Fix reST syntax of a title files: pep-0418.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -259,7 +259,7 @@ is 1 nanosecond. Precision --------- +--------- The precision is the effective smallest difference between two timestamps of the clock. It does not reflect the stability the clock rate. For example, -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 01:07:04 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 01:07:04 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Integrate_Jim_Jewet?= =?utf8?q?t=27s_Glossary?= Message-ID: http://hg.python.org/peps/rev/23127be44be3 changeset: 4226:23127be44be3 user: Victor Stinner date: Thu Apr 12 01:06:31 2012 +0200 summary: PEP 418: Integrate Jim Jewett's Glossary files: pep-0418.txt | 121 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 118 insertions(+), 3 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -2,7 +2,7 @@ Title: Add a monotonic time functions Version: $Revision$ Last-Modified: $Date$ -Author: Victor Stinner +Author: Jim Jewett , Victor Stinner Status: Draft Type: Standards Track Content-Type: text/x-rst @@ -247,8 +247,123 @@ daemon) -Definitions -=========== +Glossary +======== + +:Accuracy: + Is the answer correct? Any clock will eventually ; if a clock is + intended to match , it will need to be back to the + "true" time. + +:Adjusted: + Resetting a clock to the correct time. This may be done either with a + or by . + +:Civil Time: + Time of day; external to the system. 10:45:13am is a Civil time; 45 seconds + is not. Provided by existing function time.localtime() and time.gmtime(). + Not changed by this PEP. + +:Clock: + An instrument for measuring time. Different clocks have different + characteristics; for example, a clock with may + start to after a few minutes, while a less precise clock remained + accurate for days. This PEP is primarily concerned with clocks which use a + unit of seconds. + +:Counter: + A clock which increments each time a certain event occurs. A counter is + , but not . It can be used to generate + a unique (and ordered) timestamp, but these timestamps cannot be mapped to + ; tick creation may well be bursty, with several advances in the + same millisecond followed by several days without any advance. + +:CPU Time: + A measure of how much CPU effort has been spent on a certain task. CPU + seconds are often normalized (so that a variable number can occur in the + same actual second). CPU seconds can be important when profiling, but they + do not map directly to user response time, nor are they directly comparable + to (real time) seconds. + +:Duration: + Elapsed time. The difference between the starting and ending times. A + defined creates an implicit (and usually large) duration. More + precision can generally be provided for a relatively small . + +:Drift: + The accumulated error against "true" time, as defined externally to the + system. + +:Epoch: + The reference point of a clock. For clocks providing , this is + often midnight as the day (and year) rolled over to January 1, 1970. For a + clock, the epoch may be undefined (represented as None). + +:Latency: + Delay. By the time a clock call returns, the has advanced, + possibly by more than the precision of the clock. + +:Monotonic: + The characteristics expected of a monotonic clock in practice. Moving in at + most one direction; for clocks, that direction is forward. The + should also be , and should be convertible to a unit of seconds. + The tradeoffs often include lack of a defined or mapping to , and being more expensive (in , power usage, or + spent within calls to the clock itself) to use. For example, the clock may + represent (a constant multiplied by) ticks of a specific quartz timer on a + specific CPU core, and calls would therefore require synchronization between + cores. + +:Precision: + Significant Digits. What is the smallest duration that the clock can + distinguish? This differs from in that a difference greater + than the minimum precision is actually meaningful. + +:Process Time: + Time elapsed since the process began. It is typically measured in rather than , and typically does not advance while the + process is suspended. + +:Real Time: + Time in the real world. This differs from in that it is not + , but they should otherwise advance in lockstep. It is not + related to the "real time" of "Real Time [Operating] Systems". It is + sometimes called "wall clock time" to avoid that ambiguity; unfortunately, + that introduces different ambiguities. + +:Resolution: + Represented Digits. Note that many clocks will have a resolution greater + than their actual . + +:Slew: + A slight change to a clock's speed, usually intended to correct with + respect to an external authority. + +:Stability: + Persistence of accuracy. A measure of expected . + +:Steady: + A clock with high and relatively high and + . In practice, it is often used to indicate a + clock, but places greater emphasis on the consistency of the duration + between subsequent ticks. + +:Step: + An instantaneous change in the represented time. Instead of speeding or + slowing the clock (), a single offset is permanently added. + +:System Time: + Time as represented by the Operating System. + +:Thread Time: + Time elapsed since the thread began. It is typically measured in + rather than , and typically does not advance while the thread is + idle. + +:Wallclock: + What the clock on the wall says. This is typically used as a synonym for + ; unfortunately, wall time is itself ambiguous. + Resolution ---------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 01:13:16 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 01:13:16 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Remove_duplicate_de?= =?utf8?q?finitions?= Message-ID: http://hg.python.org/peps/rev/db06bfe4cce3 changeset: 4227:db06bfe4cce3 user: Victor Stinner date: Thu Apr 12 01:12:42 2012 +0200 summary: PEP 418: Remove duplicate definitions files: pep-0418.txt | 33 --------------------------------- 1 files changed, 0 insertions(+), 33 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -365,43 +365,6 @@ ; unfortunately, wall time is itself ambiguous. -Resolution ----------- - -The resolution is the smallest difference between two timestamps supported by -the format used by the clock. For example, clock_gettime() uses a timespec -structure which has two integer fields, tv_sec and tv_nsec, so the resolution -is 1 nanosecond. - -Precision ---------- - -The precision is the effective smallest difference between two timestamps of the -clock. It does not reflect the stability the clock rate. For example, -QueryPerformanceCounter() has a good precision but is known to not have a steady -rate. - - -Monotonic ---------- - -A monotonic clock cannot go backward. It may give the same value for two close -reads depending on the clock resolution. - -On Linux, CLOCK_MONOTONIC is a monotonic clock but its rate is adjusted by NTP. - -Steady ------- - -A steady clock is a clock with a stable rate. - -The `C++ Timeout Specification -`_ uses the -following definition: "Objects of class steady_clock represent clocks for which -values of time_point advance at a steady rate relative to real time. That is, -the clock may not be adjusted." - - Hardware clocks =============== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 01:22:56 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 01:22:56 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Move_Linux_clocksou?= =?utf8?q?rce_and_FreeBSD_timecounter?= Message-ID: http://hg.python.org/peps/rev/81e4519bdde9 changeset: 4228:81e4519bdde9 user: Victor Stinner date: Thu Apr 12 01:22:23 2012 +0200 summary: PEP 418: Move Linux clocksource and FreeBSD timecounter Remove duplicate info on hardware clocks files: pep-0418.txt | 174 +++++++++++++++++++------------------- 1 files changed, 88 insertions(+), 86 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -368,17 +368,20 @@ Hardware clocks =============== -* HPET: An HPET chip consists of a 64-bit up-counter (main counter) +List of hardware clocks +----------------------- + +* HPET: An High Precision Event Timer (HPET) chip consists of a 64-bit up-counter (main counter) counting at least at 10 MHz and a set of up to 256 comparators (at - least 3). Each HPET can have up to 32 timers. + least 3). Each HPET can have up to 32 timers. HPET can cause around 3 seconds of drift per day. * TSC (Time Stamp Counter): Historically, the TSC increased with every internal processor clock cycle, but now the rate is usually constant (even if the processor changes frequency) and usually equals the maximum processor frequency. Multiple cores having different TSC values. Hibernation of system will reset TSC value. The RDTSC instruction can be used to read this counter. CPU frequency scaling for power saving. -* ACPI PMTMR (Power Management TiMeR): ACPI 24-bit timer with a frequency - of 3.5 MHz (3,579,545 Hz). HPET can cause around 3 seconds of drift per day. +* ACPI Power Management Timer: ACPI 24-bit timer with a frequency + of 3.5 MHz (3,579,545 Hz). * Cyclone: The Cyclone timer uses a 32-bit counter on IBM Extended X-Architecture (EXA) chipsets which include computers that use the IBM "Summit" series chipsets (ex: x440). This is available in IA32 @@ -388,6 +391,84 @@ * RTC (Real-time clock). Most RTCs use a crystal oscillator with a frequency of 32,768 Hz + +Linux clocksource +----------------- + +There were 4 implementations of the time in the Linux kernel: UTIME +(1996), timer wheel (1997), HRT (2001) and hrtimers (2007). The +latter is the result of the "high-res-timers" project started by +George Anzinger in 2001, with contributions by Thomas Gleixner and +Douglas Niehaus. hrtimers implementation was merged into Linux +2.6.21, released in 2007. + +hrtimers supports various clock sources. It sets a priority to each +source to decide which one will be used. Linux supports the following +clock sources: + +* tsc +* hpet +* pit +* pmtmr: ACPI Power Management Timer +* cyclone + +High-resolution timers are not supported on all hardware +architectures. They are at least provided on x86/x86_64, ARM and +PowerPC. + +The /sys/devices/system/clocksource/clocksource0 directory contains two useful files: + + * available_clocksource: list of available clock sources + * current_clocksource: clock source currently used. It is possible to change + the current clocksource by writing the name of a clocksource into this + file. + +/proc/timer_list contains the list of all hardware timers. + +Read also the `time(7) manual page +`_: +"overview of time and timers". + + +FreeBSD timecounter +------------------- + +kern.timecounter.choice list available hardward clocks with their priority. +The sysctl program can be used to change the timecounter. Example:: + + # dmesg|grep Timecounter + Timecounter "i8254" frequency 1193182 Hz quality 0 + Timecounter "ACPI-safe" frequency 3579545 Hz quality 850 + Timecounter "HPET" frequency 100000000 Hz quality 900 + Timecounter "TSC" frequency 3411154800 Hz quality 800 + Timecounters tick every 10.000 msec + # sysctl kern.timecounter.choice + kern.timecounter.choice: TSC(800) HPET(900) ACPI-safe(850) i8254(0) dummy(-1000000) + # sysctl kern.timecounter.hardware="ACPI-fast" + kern.timecounter.hardware: HPET -> ACPI-fast + +Available clocks: + + * "TSC": Time Stamp Counter of the procesor + * "HPET": High Precision Event Timer + * "ACPI-fast": ACPI Power Management timer (fast mode) + * "ACPI-safe": ACPI Power Management timer (safe mode) + * "i8254": PIT with Intel 8254 chipset + +The `commit 222222 +`_ (May 2011) +decreased ACPI-fast timecounter quality to 900 and increased HPET timecounter +quality to 950: "HPET on modern platforms usually have better resolution and +lower latency than ACPI timer". + +Read `Timecounters: Efficient and precise timekeeping in SMP kernels +`_ by Poul-Henning Kamp (2002) for +the FreeBSD Project. + + +Performances +------------ + Reading an hardware clock has a cost. The following table compares the performance of different hardware clocks on Linux 3.3 with Intel Core i7-2600 at 3.40GHz (8 cores). @@ -914,90 +995,6 @@ QueryUnbiasedInterruptTime() was introduced in Windows 7. -Linux timers ------------- - -There were 4 implementations of the time in the Linux kernel: UTIME -(1996), timer wheel (1997), HRT (2001) and hrtimers (2007). The -latter is the result of the "high-res-timers" project started by -George Anzinger in 2001, with contributions by Thomas Gleixner and -Douglas Niehaus. hrtimers implementation was merged into Linux -2.6.21, released in 2007. - -hrtimers supports various clock sources. It sets a priority to each -source to decide which one will be used. - -* TSC (Time Stamp Counter): Internal processor clock incremented at - each processor cycle. Its frequency is the processor frequency and - so usually higher than 1 GHz. Its priority is 300 by default, but - falls to 0 if the processor frequency changes and the counter - becomes unstable. -* HPET: An High Precision Event Timer (HPET) chip consists of a 64-bit - up-counter (main counter) counting at least at 10 MHz and a set of up to 256 - comparators (at least 3). Each HPET can have up to 32 timers. HPET can - cause around 3 seconds of drift per day. -* PIT (programmable interrupt timer): Intel 8253/8254 chipsets with a - configurable frequency in range 18.2 Hz - 1.2 MHz. Linux uses the - frequency 1,193,181.8 Hz. It is a 16-bit counter. -* PMTMR (power management timer): ACPI 24-bit timer with a frequency - of 3.5 MHz (3,579,545 Hz). Its priority is 200 by default, but - changes to 110 if the chipset is broken and need a software - workaround. -* Cyclone: The Cyclone timer uses a 32-bit counter on IBM Extended - X-Architecture (EXA) chipsets which include computers that use the - IBM "Summit" series chipsets (ex: x440). This is available in IA32 - and IA64 architectures. - -High-resolution timers are not supported on all hardware -architectures. They are at least provided on x86/x86_64, ARM and -PowerPC. - -The list of available clock sources can be read in -/sys/devices/system/clocksource/clocksource0/available_clocksource. -It is possible to force a clocksource at runtime by writing its name -into /sys/devices/system/clocksource/clocksource0/current_clocksource. -/proc/timer_list contains the list of all hardware timers. - -Read also the `time(7) manual page -`_: -"overview of time and timers". - -FreeBSD timers --------------- - -kern.timecounter.choice list available hardward clocks with their priority. -The sysctl program can be used to change the timecounter. Example:: - - # dmesg|grep Timecounter - Timecounter "i8254" frequency 1193182 Hz quality 0 - Timecounter "ACPI-safe" frequency 3579545 Hz quality 850 - Timecounter "HPET" frequency 100000000 Hz quality 900 - Timecounter "TSC" frequency 3411154800 Hz quality 800 - Timecounters tick every 10.000 msec - # sysctl kern.timecounter.choice - kern.timecounter.choice: TSC(800) HPET(900) ACPI-safe(850) i8254(0) dummy(-1000000) - # sysctl kern.timecounter.hardware="ACPI-fast" - kern.timecounter.hardware: HPET -> ACPI-fast - -Available clocks: - - * "TSC": Time Stamp Counter of the procesor - * "HPET": High Precision Event Timer - * "ACPI-fast": ACPI Power Management timer (fast mode) - * "ACPI-safe": ACPI Power Management timer (safe mode) - * "i8254": PIT with Intel 8254 chipset - -The `commit 222222 -`_ (May 2011) -decreased ACPI-fast timecounter quality to 900 and increased HPET timecounter -quality to 950: "HPET on modern platforms usually have better resolution and -lower latency than ACPI timer". - -Read `Timecounters: Efficient and precise timekeeping in SMP kernels -`_ by Poul-Henning Kamp (2002) for -the FreeBSD Project. - - Sleep, suspend and monotonic time ================================= @@ -1062,6 +1059,7 @@ WaitForSingleObject() 1 ms ======================== ========== + Classic functions ----------------- @@ -1072,6 +1070,7 @@ `_ * delay(milliseconds) + clock_nanosleep --------------- @@ -1088,6 +1087,7 @@ clock_settime(2) shall have no effect on a thread that is blocked on a relative clock_nanosleep(). + select() -------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 01:26:53 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 01:26:53 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Use_different_names?= =?utf8?q?_for_manpage_links?= Message-ID: http://hg.python.org/peps/rev/1b20acb55218 changeset: 4229:1b20acb55218 user: Victor Stinner date: Thu Apr 12 01:26:17 2012 +0200 summary: PEP 418: Use different names for manpage links files: pep-0418.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1065,8 +1065,8 @@ * sleep(seconds) * usleep(microseconds) - * nanosleep(nanoseconds, remaining) - `Linux manpage + * nanosleep(nanoseconds, remaining): + `Linux manpage of nanosleep() `_ * delay(milliseconds) @@ -1075,7 +1075,7 @@ --------------- clock_nanosleep(clock_id, flags, nanoseconds, remaining): -`Linux manpage +`Linux manpage of clock_nanosleep() `_. If flags is TIMER_ABSTIME, then request is interpreted as an absolute -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 01:43:57 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 01:43:57 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Make_it_more_explic?= =?utf8?q?it_than_realtime_does_include_time_elapsed_during?= Message-ID: http://hg.python.org/peps/rev/b6cd7b9f8dc1 changeset: 4230:b6cd7b9f8dc1 user: Victor Stinner date: Thu Apr 12 01:43:22 2012 +0200 summary: PEP 418: Make it more explicit than realtime does include time elapsed during sleep, whereas process time does not. files: pep-0418.txt | 32 ++++++++++++++++---------------- 1 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -811,15 +811,15 @@ System time clocks ------------------ -========================= =============== -Name Resolution -========================= =============== -CLOCK_REALTIME 1 ns -GetSystemTimeAsFileTime 100 ns -gettimeofday() 1 ?s -ftime() 1 ms -time() 1 sec -========================= =============== +========================= =============== ============= +Name Resolution Include sleep +========================= =============== ============= +CLOCK_REALTIME 1 ns Yes +GetSystemTimeAsFileTime 100 ns Yes +gettimeofday() 1 ?s Yes +ftime() 1 ms Yes +time() 1 sec Yes +========================= =============== ============= Examples of clock precision on x86_64: @@ -885,13 +885,13 @@ The process time cannot be set. It is not monotonic: the clocks stop while the process is idle. -========================= =============== -Name Resolution -========================= =============== -GetProcessTimes() 100 ns -CLOCK_PROCESS_CPUTIME_ID 1 ns -clock() \- -========================= =============== +========================= =============== ============= +Name Resolution Include sleep +========================= =============== ============= +GetProcessTimes() 100 ns No +CLOCK_PROCESS_CPUTIME_ID 1 ns No +clock() \- No +========================= =============== ============= Examples of clock precision on x86_64: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 02:41:05 2012 From: python-checkins at python.org (r.david.murray) Date: Thu, 12 Apr 2012 02:41:05 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NTUyOiByZW1v?= =?utf8?q?ve_redundant_wording_in_=27test=27_docs=2E?= Message-ID: http://hg.python.org/cpython/rev/f25fb7e1d076 changeset: 76258:f25fb7e1d076 branch: 3.2 parent: 76256:19fd998d1e15 user: R David Murray date: Wed Apr 11 20:11:53 2012 -0400 summary: #14552: remove redundant wording in 'test' docs. Original patch by Tshepang Lekhonkhobe. files: Doc/library/test.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -171,9 +171,9 @@ Running :mod:`test` directly allows what resources are available for tests to use to be set. You do this by using the ``-u`` command-line -option. Run :program:`python -m test -uall` to turn on all -resources; specifying ``all`` as an option for ``-u`` enables all -possible resources. If all but one resource is desired (a more common case), a +option. Specifying ``all`` as the value for the ``-u`` option enables all +possible resources: :program:`python -m test -uall`. +If all but one resource is desired (a more common case), a comma-separated list of resources that are not desired may be listed after ``all``. The command :program:`python -m test -uall,-audio,-largefile` will run :mod:`test` with all resources except the ``audio`` and -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 02:41:06 2012 From: python-checkins at python.org (r.david.murray) Date: Thu, 12 Apr 2012 02:41:06 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NTUzOiBmaXgg?= =?utf8?q?word_order=2E?= Message-ID: http://hg.python.org/cpython/rev/ed5788424c34 changeset: 76259:ed5788424c34 branch: 3.2 user: R David Murray date: Wed Apr 11 20:13:25 2012 -0400 summary: #14553: fix word order. Patch by Tshepang Lekhonkhobe. files: Doc/library/http.server.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -333,7 +333,7 @@ httpd.serve_forever() :mod:`http.server` can also be invoked directly using the :option:`-m` -switch of the interpreter a with ``port number`` argument. Similar to +switch of the interpreter with a ``port number`` argument. Similar to the previous example, this serves files relative to the current directory. :: python -m http.server 8000 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 02:41:07 2012 From: python-checkins at python.org (r.david.murray) Date: Thu, 12 Apr 2012 02:41:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_doc_fixes_=2314553_and_=2314552=2E?= Message-ID: http://hg.python.org/cpython/rev/bd353f12c007 changeset: 76260:bd353f12c007 parent: 76257:91f161335689 parent: 76259:ed5788424c34 user: R David Murray date: Wed Apr 11 20:15:10 2012 -0400 summary: Merge doc fixes #14553 and #14552. files: Doc/library/http.server.rst | 2 +- Doc/library/test.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -352,7 +352,7 @@ httpd.serve_forever() :mod:`http.server` can also be invoked directly using the :option:`-m` -switch of the interpreter a with ``port number`` argument. Similar to +switch of the interpreter with a ``port number`` argument. Similar to the previous example, this serves files relative to the current directory. :: python -m http.server 8000 diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -172,9 +172,9 @@ Running :mod:`test` directly allows what resources are available for tests to use to be set. You do this by using the ``-u`` command-line -option. Run :program:`python -m test -uall` to turn on all -resources; specifying ``all`` as an option for ``-u`` enables all -possible resources. If all but one resource is desired (a more common case), a +option. Specifying ``all`` as the value for the ``-u`` option enables all +possible resources: :program:`python -m test -uall`. +If all but one resource is desired (a more common case), a comma-separated list of resources that are not desired may be listed after ``all``. The command :program:`python -m test -uall,-audio,-largefile` will run :mod:`test` with all resources except the ``audio`` and -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 02:41:07 2012 From: python-checkins at python.org (r.david.murray) Date: Thu, 12 Apr 2012 02:41:07 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0NTUyOiByZW1v?= =?utf8?q?ve_redundant_wording_in_=27test=27_docs=2E?= Message-ID: http://hg.python.org/cpython/rev/d60ef141e090 changeset: 76261:d60ef141e090 branch: 2.7 parent: 76254:5d5573d94988 user: R David Murray date: Wed Apr 11 20:38:45 2012 -0400 summary: #14552: remove redundant wording in 'test' docs. Original patch by Tshepang Lekhonkhobe. files: Doc/library/test.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -169,10 +169,10 @@ the test passed or failed and thus minimize output. Running :mod:`test.regrtest` directly allows what resources are available for -tests to use to be set. You do this by using the :option:`-u` command-line -option. Run :program:`python -m test.regrtest -uall` to turn on all -resources; specifying ``all`` as an option for ``-u`` enables all -possible resources. If all but one resource is desired (a more common case), a +tests to use to be set. You do this by using the ``-u`` command-line +option. Specifying ``all`` as the value for the ``-u`` option enables all +possible resources: :program:`python -m test -uall`. +If all but one resource is desired (a more common case), a comma-separated list of resources that are not desired may be listed after ``all``. The command :program:`python -m test.regrtest -uall,-audio,-largefile` will run :mod:`test.regrtest` with all resources except the ``audio`` and -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Apr 12 05:35:57 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 12 Apr 2012 05:35:57 +0200 Subject: [Python-checkins] Daily reference leaks (bd353f12c007): sum=2 Message-ID: results for bd353f12c007 on branch "default" -------------------------------------------- test_support leaked [2, 0, 0] references, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogjZnmuB', '-x'] From python-checkins at python.org Thu Apr 12 13:28:32 2012 From: python-checkins at python.org (senthil.kumaran) Date: Thu, 12 Apr 2012 13:28:32 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_code_improvement=2E_=27as_c?= =?utf8?q?m=27_not_required_when_not_used=2E_Review_comment_by_Georg?= Message-ID: http://hg.python.org/cpython/rev/0f114b855824 changeset: 76262:0f114b855824 parent: 76260:bd353f12c007 user: Senthil Kumaran date: Thu Apr 12 19:28:07 2012 +0800 summary: code improvement. 'as cm' not required when not used. Review comment by Georg Brandl files: Lib/test/test_urllib2.py | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -619,19 +619,19 @@ def test_method_deprecations(self): req = Request("http://www.example.com") - with self.assertWarns(DeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning): req.add_data("data") - with self.assertWarns(DeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning): req.has_data() - with self.assertWarns(DeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning): req.get_data() - with self.assertWarns(DeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning): req.get_host() - with self.assertWarns(DeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning): req.get_selector() - with self.assertWarns(DeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning): req.is_unverifiable() - with self.assertWarns(DeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning): req.get_origin_req_host() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 13:40:36 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 13:40:36 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_time=2Eperf=5Fc?= =?utf8?b?b3VudGVyKCksIHRpbWUucHJvY2Vzc190aW1lKCksIGRlcHJlY2F0ZSB0aW1lLmNs?= =?utf8?b?b2NrKCk=?= Message-ID: http://hg.python.org/peps/rev/fb41f0b2e1bd changeset: 4231:fb41f0b2e1bd user: Victor Stinner date: Thu Apr 12 13:38:06 2012 +0200 summary: PEP 418: Add time.perf_counter(), time.process_time(), deprecate time.clock() Reorder also sections. files: pep-0418.txt | 300 ++++++++++++++++++++++++-------------- 1 files changed, 187 insertions(+), 113 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1,5 +1,5 @@ PEP: 418 -Title: Add a monotonic time functions +Title: Add monotonic time, performance counter and process time functions Version: $Revision$ Last-Modified: $Date$ Author: Jim Jewett , Victor Stinner @@ -13,7 +13,8 @@ Abstract ======== -Add time.monotonic() and time.get_clock_info(name) functions to Python 3.3. +Add time.get_clock_info(name), time.monotonic(), time.perf_counter() and +time.process_time() functions to Python 3.3. Rationale @@ -25,62 +26,74 @@ automatically by NTP. A monotonic clock should be used instead to not be affected by system clock updates. -Clocks: +To measure the performance of a function, time.clock() can be used but it +is very different on Windows and on Unix. On Windows, time.clock() includes +time elapsed during sleep, whereas it does not on Unix. time.clock() precision +is very good on Windows, but very bad on Unix. A new time.perf_counter() should +be used instead to always get the most precise performance counter with a +portable behaviour. - * time.time(): system clock - * time.monotonic(): monotonic clock +To measure CPU time, Python does not provide directly a portable function. +time.clock() can be used on Unix, but it has a bad precision. +resource.getrusage() can also be used on Unix, but it requires to get fields of +a structure and compute the sum of time spend in kernel space and user space. +A new time.process_time() function is portable counter, always measure CPU time +(don't include time elapsed during sleep), and has the best available +precision. +Each operating system implements clocks and performance counters differently, +and it is useful to know exactly which function is used and some properties of +the clock like its resolution and its precision. A new time.get_clock_info() +function gives access to all available information of each Python time +function. -Functions -========= +New functions: -To fulfill the use cases, the functions' properties are: + * time.monotonic(): timeout and scheduling, not affected by system clock + updates + * time.perf_counter(): benchmarking, most precise clock for short period + * time.process_time(): profiling, CPU time of the process -* time.time(): system clock, "wall clock". -* time.monotonic(): monotonic clock -* time.get_clock_info(name): get information on the specified time function +time.clock() is deprecated by this PEP because it is not portable: +time.perf_counter() or time.process_time() should be used instead, depending +on your requirements. -time.time() ------------ +Python functions +================ -The system time is the "wall clock". It can be set manually by the -system administrator or automatically by a NTP daemon. It can jump -backward and forward. It is not monotonic. +New functions +------------- -It is available on all platforms and cannot fail. +time.get_clock_info(name) +^^^^^^^^^^^^^^^^^^^^^^^^^ -Pseudo-code [#pseudo]_:: +Get information on the specified clock. Supported clocks: - if os.name == "nt": - def time(): - return _time.GetSystemTimeAsFileTime() - else: - def time(): - if hasattr(time, "clock_gettime"): - try: - # resolution = 1 nanosecond - return time.clock_gettime(time.CLOCK_REALTIME) - except OSError: - # CLOCK_REALTIME is not supported (unlikely) - pass - if hasattr(_time, "gettimeofday"): - try: - # resolution = 1 microsecond - return _time.gettimeofday() - except OSError: - # gettimeofday() should not fail - pass - if hasattr(_time, "ftime"): - # resolution = 1 millisecond - return _time.ftime() - else: - # resolution = 1 second - return _time.time() + * "clock": time.clock() + * "monotonic": time.monotonic() + * "perf_counter": time.perf_counter() + * "process_time": time.process_time() + * "time": time.time() + +Return a dictionary with the following keys: + + * Mandatory keys: + + * "function" (str): name of the underlying operating system function. + Examples: "QueryPerformanceCounter()", "clock_gettime(CLOCK_REALTIME)". + * "resolution" (float): resolution in seconds of the clock + * "is_monotonic" (bool): True if the clock cannot go backward + + * Optional keys: + + * "precision" (float): precision in seconds of the clock + * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a NTP + daemon) time.monotonic() ----------------- +^^^^^^^^^^^^^^^^ Monotonic clock, cannot go backward. It is not affected by system clock updates. The reference point of the returned value is undefined so only the @@ -138,8 +151,117 @@ running for more than 49 days. +time.perf_counter() +^^^^^^^^^^^^^^^^^^^ + +Performance counter used for benchmarking. It is monotonic, cannot go backward. +It does include time elapsed during sleep. The reference point of the returned +value is undefined so only the difference between consecutive calls is valid +and is number of seconds. + +Pseudo-code:: + + def perf_counter(): + if perf_counter.use_performance_counter: + if perf_counter.perf_frequency is None: + try: + perf_counter.perf_frequency = float(_time.QueryPerformanceFrequency()) + except OSError: + # QueryPerformanceFrequency() fails if the installed + # hardware does not support a high-resolution performance + # counter + perf_counter.use_performance_counter = False + else: + return _time.QueryPerformanceCounter() / perf_counter.perf_frequency + else: + return _time.QueryPerformanceCounter() / perf_counter.perf_frequency + if perf_counter.use_monotonic: + # Monotonic clock is preferred over system clock + try: + return time.monotonic() + except OSError: + perf_counter.use_monotonic = False + return time.time() + perf_counter.use_performance_counter = (os.name == 'nt') + if perf_counter.use_performance_counter: + perf_counter.perf_frequency = None + perf_counter.use_monotonic = hasattr(time, 'monotonic') + + +time.process_time() +^^^^^^^^^^^^^^^^^^^ + +Process time used for profiling: some of kernel and user-space CPU +time. It does not include time elapsed during sleep. The reference point of +the returned value is undefined so only the difference between consecutive +calls is valid. + +Pseudo-code:: + + if os.name == 'nt': + def process_time(): + handle = win32process.GetCurrentProcess() + process_times = win32process.GetProcessTimes(handle) + return (process_times['UserTime'] + process_times['KernelTime']) * 1e-7 + elif (hasattr(time, 'clock_gettime') + and hasattr(time, 'CLOCK_PROCESS_CPUTIME_ID')): + def process_time(): + return time.clock_gettime(time.CLOCK_PROCESS_CPUTIME_ID) + else: + try: + import resource + except ImportError: + def process_time(): + return _time.clock() + else: + def process_time(): + usage = resource.getrusage(resource.RUSAGE_SELF) + return usage[0] + usage[1] + + +Existing functions +------------------ + +time.time() +^^^^^^^^^^^ + +The system time is the "wall clock". It can be set manually by the +system administrator or automatically by a NTP daemon. It can jump +backward and forward. It is not monotonic. + +It is available on all platforms and cannot fail. + +Pseudo-code [#pseudo]_:: + + if os.name == "nt": + def time(): + return _time.GetSystemTimeAsFileTime() + else: + def time(): + if hasattr(time, "clock_gettime"): + try: + # resolution = 1 nanosecond + return time.clock_gettime(time.CLOCK_REALTIME) + except OSError: + # CLOCK_REALTIME is not supported (unlikely) + pass + if hasattr(_time, "gettimeofday"): + try: + # resolution = 1 microsecond + return _time.gettimeofday() + except OSError: + # gettimeofday() should not fail + pass + if hasattr(_time, "ftime"): + # resolution = 1 millisecond + return _time.ftime() + else: + # resolution = 1 second + return _time.time() + + time.sleep() ------------- +^^^^^^^^^^^^ Suspend execution for the given number of seconds. The actual suspension time may be less than that requested because any caught signal will terminate the @@ -184,9 +306,11 @@ seconds = int(seconds) _time.sleep(seconds) +Deprecated functions +-------------------- time.clock() ------------- +^^^^^^^^^^^^ On Unix, return the current processor time as a floating point number expressed in seconds. The precision, and in fact the very definition of the meaning of @@ -222,30 +346,6 @@ clock = _time.clock -time.get_clock_info(name) -------------------------- - -Get information on the specified clock. Supported clocks: - - * "clock": time.clock() - * "monotonic": time.monotonic() - * "time": time.time() - -Return a dictionary with the following keys: - - * Mandatory keys: - - * "function" (str): name of the underlying operating system function. - Examples: "QueryPerformanceCounter()", "clock_gettime(CLOCK_REALTIME)". - * "resolution" (float): resolution in seconds of the clock - * "is_monotonic" (bool): True if the clock cannot go backward - - * Optional keys: - - * "precision" (float): precision in seconds of the clock - * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a NTP - daemon) - Glossary ======== @@ -890,6 +990,7 @@ ========================= =============== ============= GetProcessTimes() 100 ns No CLOCK_PROCESS_CPUTIME_ID 1 ns No +getrusage() 1 ?s No clock() \- No ========================= =============== ============= @@ -899,9 +1000,10 @@ Name Operating system Precision ========================= ================ =============== CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns -clock() Linux 3.2 1 ?s clock() SunOS 5.11 1 ?s +getrusage() Linux 3.0 4 ms clock() FreeBSD 8.2 7.8 ms +clock() Linux 3.2 10 ms clock() OpenBSD 5.0 10 ms GetProcessTimes() Windows Seven 15.6 ms ========================= ================ =============== @@ -937,6 +1039,10 @@ * The clock resolution can be read using clock_getres(). * GetProcessTimes(): call GetSystemTimeAdjustment(). +Python source code includes a portable library to get the process time (CPU +time): `Tools/pybench/systimes.py +`_. + Thread time ----------- @@ -1123,8 +1229,10 @@ Alternatives: API design ======================== -Other names for time.monotonic() --------------------------------- +Other names for new functions +----------------------------- + +time.monotonic(): * time.counter() * time.seconds() @@ -1136,6 +1244,12 @@ The name "time.try_monotonic()" was also proposed when time.monotonic() was falling back to the system clock when no monotonic clock was available. +time.perf_counter(): + + * time.hires() + * time.highres() + * time.timer() + Only expose operating system clocks ----------------------------------- @@ -1234,52 +1348,6 @@ see the same clock value -Deferred API: time.perf_counter() -================================= - -Performance counter used for benchmarking and profiling. The reference point of -the returned value is undefined so only the difference between consecutive calls is -valid and is number of seconds. - -Pseudo-code:: - - def perf_counter(): - if perf_counter.use_performance_counter: - if perf_counter.perf_frequency is None: - try: - perf_counter.perf_frequency = float(_time.QueryPerformanceFrequency()) - except OSError: - # QueryPerformanceFrequency() fails if the installed - # hardware does not support a high-resolution performance - # counter - perf_counter.use_performance_counter = False - else: - return _time.QueryPerformanceCounter() / perf_counter.perf_frequency - else: - return _time.QueryPerformanceCounter() / perf_counter.perf_frequency - if perf_counter.use_monotonic: - # Monotonic clock is preferred over system clock - try: - return time.monotonic() - except OSError: - perf_counter.use_monotonic = False - return time.time() - perf_counter.use_performance_counter = (os.name == 'nt') - if perf_counter.use_performance_counter: - perf_counter.perf_frequency = None - perf_counter.use_monotonic = hasattr(time, 'monotonic') - -Other names proposed for time.perf_counter(): - - * time.hires() - * time.highres() - * time.timer() - -Python source code includes a portable library to get the process time (CPU -time): `Tools/pybench/systimes.py -`_. - - Footnotes ========= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 14:01:54 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 14:01:54 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_CLOCK=5FBOOTTIM?= =?utf8?q?E_to_monotonic_clocks?= Message-ID: http://hg.python.org/peps/rev/5129c36a97f3 changeset: 4232:5129c36a97f3 user: Victor Stinner date: Thu Apr 12 14:01:02 2012 +0200 summary: PEP 418: Add CLOCK_BOOTTIME to monotonic clocks files: pep-0418.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -660,6 +660,7 @@ CLOCK_HIGHRES 1 ns No Yes ? CLOCK_MONOTONIC 1 ns Slewed on Linux Yes No CLOCK_MONOTONIC_RAW 1 ns No Yes No +CLOCK_BOOTTIME 1 ns ? Yes Yes mach_absolute_time() 1 ns No Yes No QueryPerformanceCounter() \- No Yes ? GetTickCount[64]() 1 ms No Yes Yes -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 19:12:31 2012 From: python-checkins at python.org (georg.brandl) Date: Thu, 12 Apr 2012 19:12:31 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_editing=2E?= Message-ID: http://hg.python.org/peps/rev/6a28c78fef65 changeset: 4233:6a28c78fef65 user: Georg Brandl date: Thu Apr 12 19:12:48 2012 +0200 summary: PEP 418: editing. files: pep-0418.txt | 704 ++++++++++++++++++++------------------ 1 files changed, 367 insertions(+), 337 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -13,50 +13,54 @@ Abstract ======== -Add time.get_clock_info(name), time.monotonic(), time.perf_counter() and -time.process_time() functions to Python 3.3. +This PEP proposes to add ``time.get_clock_info(name)``, +``time.monotonic()``, ``time.perf_counter()`` and +``time.process_time()`` functions to Python 3.3. Rationale ========= -If a program uses the system clock to schedule events or to implement a -timeout, it will not run events at the right moment or stop the timeout too -early or too late when the system clock is set manually or adjusted -automatically by NTP. A monotonic clock should be used instead to not be -affected by system clock updates. +If a program uses the system clock to schedule events or to implement +a timeout, it will not run events at the right moment or stop the +timeout too early or too late when the system clock is set manually or +adjusted automatically by NTP. A monotonic clock should be used +instead to not be affected by system clock updates. -To measure the performance of a function, time.clock() can be used but it -is very different on Windows and on Unix. On Windows, time.clock() includes -time elapsed during sleep, whereas it does not on Unix. time.clock() precision -is very good on Windows, but very bad on Unix. A new time.perf_counter() should -be used instead to always get the most precise performance counter with a +To measure the performance of a function, ``time.clock()`` can be used +but it is very different on Windows and on Unix. On Windows, +``time.clock()`` includes time elapsed during sleep, whereas it does +not on Unix. ``time.clock()`` precision is very good on Windows, but +very bad on Unix. The new ``time.perf_counter()`` function can be +used instead to always get the most precise performance counter with a portable behaviour. -To measure CPU time, Python does not provide directly a portable function. -time.clock() can be used on Unix, but it has a bad precision. -resource.getrusage() can also be used on Unix, but it requires to get fields of -a structure and compute the sum of time spend in kernel space and user space. -A new time.process_time() function is portable counter, always measure CPU time -(don't include time elapsed during sleep), and has the best available +To measure CPU time, Python does not provide directly a portable +function. ``time.clock()`` can be used on Unix, but it has a bad +precision. ``resource.getrusage()`` can also be used on Unix, but it +requires to get fields of a structure and compute the sum of time +spent in kernel space and user space. The new ``time.process_time()`` +function acts as a portable counter that always measures CPU time +(doesn't include time elapsed during sleep) and has the best available precision. -Each operating system implements clocks and performance counters differently, -and it is useful to know exactly which function is used and some properties of -the clock like its resolution and its precision. A new time.get_clock_info() -function gives access to all available information of each Python time -function. +Each operating system implements clocks and performance counters +differently, and it is useful to know exactly which function is used +and some properties of the clock like its resolution and its +precision. The new ``time.get_clock_info()`` function gives access to +all available information of each Python time function. New functions: - * time.monotonic(): timeout and scheduling, not affected by system clock - updates - * time.perf_counter(): benchmarking, most precise clock for short period - * time.process_time(): profiling, CPU time of the process +* ``time.monotonic()``: timeout and scheduling, not affected by system + clock updates +* ``time.perf_counter()``: benchmarking, most precise clock for short + period +* ``time.process_time()``: profiling, CPU time of the process -time.clock() is deprecated by this PEP because it is not portable: -time.perf_counter() or time.process_time() should be used instead, depending -on your requirements. +``time.clock()`` is deprecated by this PEP because it is not portable: +``time.perf_counter()`` or ``time.process_time()`` should be used +instead, depending on your requirements. Python functions @@ -68,36 +72,38 @@ time.get_clock_info(name) ^^^^^^^^^^^^^^^^^^^^^^^^^ -Get information on the specified clock. Supported clocks: +Get information on the specified clock. Supported clocks: - * "clock": time.clock() - * "monotonic": time.monotonic() - * "perf_counter": time.perf_counter() - * "process_time": time.process_time() - * "time": time.time() +* "clock": time.clock() +* "monotonic": time.monotonic() +* "perf_counter": time.perf_counter() +* "process_time": time.process_time() +* "time": time.time() Return a dictionary with the following keys: - * Mandatory keys: +* Mandatory keys: - * "function" (str): name of the underlying operating system function. - Examples: "QueryPerformanceCounter()", "clock_gettime(CLOCK_REALTIME)". - * "resolution" (float): resolution in seconds of the clock - * "is_monotonic" (bool): True if the clock cannot go backward + * "function" (str): name of the underlying operating system + function. Examples: "QueryPerformanceCounter()", + "clock_gettime(CLOCK_REALTIME)". + * "resolution" (float): resolution in seconds of the clock + * "is_monotonic" (bool): True if the clock cannot go backward - * Optional keys: +* Optional keys: - * "precision" (float): precision in seconds of the clock - * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a NTP - daemon) + * "precision" (float): precision in seconds of the clock + * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a + NTP daemon) time.monotonic() ^^^^^^^^^^^^^^^^ -Monotonic clock, cannot go backward. It is not affected by system clock -updates. The reference point of the returned value is undefined so only the -difference between consecutive calls is valid. +Monotonic clock, cannot go backward. It is not affected by system +clock updates. The reference point of the returned value is +undefined, so that only the difference between the results of +consecutive calls is valid. Availability: Windows, Mac OS X, Unix. @@ -139,25 +145,28 @@ and hasattr(time, 'CLOCK_HIGHRES')) -On Windows, QueryPerformanceCounter() is not used even though it has a better -precision than GetTickCount(). It is not reliable and has too many issues. +On Windows, ``QueryPerformanceCounter()`` is not used even though it +has a better precision than ``GetTickCount()``. It is not reliable +and has too many issues. .. note:: - time.monotonic() detects GetTickCount() integer overflow (32 bits, roll-over - after 49.7 days): it increases a delta by 2\ :sup:`32` each time than an - overflow is detected. The delta is stored in the process-local state and so - the value of time.monotonic() may be different in two Python processes + ``time.monotonic()`` detects ``GetTickCount()`` integer overflow + (32 bits, roll-over after 49.7 days): it increases a delta by 2\ + :sup:`32` each time than an overflow is detected. The delta is + stored in the process-local state and so the value of + ``time.monotonic()`` may be different in two Python processes running for more than 49 days. time.perf_counter() ^^^^^^^^^^^^^^^^^^^ -Performance counter used for benchmarking. It is monotonic, cannot go backward. -It does include time elapsed during sleep. The reference point of the returned -value is undefined so only the difference between consecutive calls is valid -and is number of seconds. +Performance counter used for benchmarking. It is monotonic, +i.e. cannot go backward. It does include time elapsed during sleep. +The reference point of the returned value is undefined, so that only +the difference between the results of consecutive calls is valid and +is number of seconds. Pseudo-code:: @@ -192,9 +201,9 @@ ^^^^^^^^^^^^^^^^^^^ Process time used for profiling: some of kernel and user-space CPU -time. It does not include time elapsed during sleep. The reference point of -the returned value is undefined so only the difference between consecutive -calls is valid. +time. It does not include time elapsed during sleep. The reference +point of the returned value is undefined, so that only the difference +between the results of consecutive calls is valid. Pseudo-code:: @@ -225,7 +234,7 @@ time.time() ^^^^^^^^^^^ -The system time is the "wall clock". It can be set manually by the +The system time is the "wall clock". It can be set manually by the system administrator or automatically by a NTP daemon. It can jump backward and forward. It is not monotonic. @@ -263,11 +272,12 @@ time.sleep() ^^^^^^^^^^^^ -Suspend execution for the given number of seconds. The actual suspension time -may be less than that requested because any caught signal will terminate the -time.sleep() following execution of that signal's catching routine. Also, the -suspension time may be longer than requested by an arbitrary amount because of -the scheduling of other activity in the system. +Suspend execution for the given number of seconds. The actual +suspension time may be less than that requested because any caught +signal will terminate the ``time.sleep()`` following execution of that +signal's catching routine. Also, the suspension time may be longer +than requested by an arbitrary amount because of the scheduling of +other activity in the system. Pseudo-code [#pseudo]_:: @@ -312,15 +322,16 @@ time.clock() ^^^^^^^^^^^^ -On Unix, return the current processor time as a floating point number expressed -in seconds. The precision, and in fact the very definition of the meaning of -"processor time", depends on that of the C function of the same name, but in any -case, this is the function to use for benchmarking Python or timing algorithms. +On Unix, return the current processor time as a floating point number +expressed in seconds. The precision, and in fact the very definition +of the meaning of "processor time", depends on that of the C function +of the same name, but in any case, this is the function to use for +benchmarking Python or timing algorithms. -On Windows, this function returns wall-clock seconds elapsed since the first -call to this function, as a floating point number, based on the Win32 function -``QueryPerformanceCounter()``. The resolution is typically better than one -microsecond. +On Windows, this function returns wall-clock seconds elapsed since the +first call to this function, as a floating point number, based on the +Win32 function ``QueryPerformanceCounter()``. The resolution is +typically better than one microsecond. Pseudo-code [#pseudo]_:: @@ -351,118 +362,126 @@ ======== :Accuracy: - Is the answer correct? Any clock will eventually ; if a clock is - intended to match , it will need to be back to the - "true" time. + Is the answer correct? Any clock will eventually ; if a + clock is intended to match , it will need to be + back to the "true" time. :Adjusted: - Resetting a clock to the correct time. This may be done either with a - or by . + Resetting a clock to the correct time. This may be done either + with a or by . :Civil Time: - Time of day; external to the system. 10:45:13am is a Civil time; 45 seconds - is not. Provided by existing function time.localtime() and time.gmtime(). - Not changed by this PEP. + Time of day; external to the system. 10:45:13am is a Civil time; + 45 seconds is not. Provided by existing function + ``time.localtime()`` and ``time.gmtime()``. Not changed by this + PEP. :Clock: An instrument for measuring time. Different clocks have different - characteristics; for example, a clock with may - start to after a few minutes, while a less precise clock remained - accurate for days. This PEP is primarily concerned with clocks which use a - unit of seconds. + characteristics; for example, a clock with + may start to after a few minutes, while a less + precise clock remained accurate for days. This PEP is primarily + concerned with clocks which use a unit of seconds. :Counter: - A clock which increments each time a certain event occurs. A counter is - , but not . It can be used to generate - a unique (and ordered) timestamp, but these timestamps cannot be mapped to - ; tick creation may well be bursty, with several advances in the - same millisecond followed by several days without any advance. + A clock which increments each time a certain event occurs. A + counter is , but not . It can + be used to generate a unique (and ordered) timestamp, but these + timestamps cannot be mapped to ; tick creation may well + be bursty, with several advances in the same millisecond followed + by several days without any advance. :CPU Time: - A measure of how much CPU effort has been spent on a certain task. CPU - seconds are often normalized (so that a variable number can occur in the - same actual second). CPU seconds can be important when profiling, but they - do not map directly to user response time, nor are they directly comparable - to (real time) seconds. + A measure of how much CPU effort has been spent on a certain task. + CPU seconds are often normalized (so that a variable number can + occur in the same actual second). CPU seconds can be important + when profiling, but they do not map directly to user response time, + nor are they directly comparable to (real time) seconds. :Duration: - Elapsed time. The difference between the starting and ending times. A - defined creates an implicit (and usually large) duration. More - precision can generally be provided for a relatively small . + Elapsed time. The difference between the starting and ending + times. A defined creates an implicit (and usually large) + duration. More precision can generally be provided for a + relatively small . :Drift: - The accumulated error against "true" time, as defined externally to the - system. + The accumulated error against "true" time, as defined externally to + the system. :Epoch: - The reference point of a clock. For clocks providing , this is - often midnight as the day (and year) rolled over to January 1, 1970. For a - clock, the epoch may be undefined (represented as None). + The reference point of a clock. For clocks providing , + this is often midnight as the day (and year) rolled over to January + 1, 1970. For a clock, the epoch may be undefined + (represented as None). :Latency: - Delay. By the time a clock call returns, the has advanced, - possibly by more than the precision of the clock. + Delay. By the time a clock call returns, the has + advanced, possibly by more than the precision of the clock. :Monotonic: - The characteristics expected of a monotonic clock in practice. Moving in at - most one direction; for clocks, that direction is forward. The - should also be , and should be convertible to a unit of seconds. - The tradeoffs often include lack of a defined or mapping to , and being more expensive (in , power usage, or - spent within calls to the clock itself) to use. For example, the clock may - represent (a constant multiplied by) ticks of a specific quartz timer on a - specific CPU core, and calls would therefore require synchronization between - cores. + The characteristics expected of a monotonic clock in practice. + Moving in at most one direction; for clocks, that direction is + forward. The should also be , and should be + convertible to a unit of seconds. The tradeoffs often include lack + of a defined or mapping to , and being more + expensive (in , power usage, or spent within + calls to the clock itself) to use. For example, the clock may + represent (a constant multiplied by) ticks of a specific quartz + timer on a specific CPU core, and calls would therefore require + synchronization between cores. :Precision: - Significant Digits. What is the smallest duration that the clock can - distinguish? This differs from in that a difference greater - than the minimum precision is actually meaningful. + Significant Digits. What is the smallest duration that the clock + can distinguish? This differs from in that a + difference greater than the minimum precision is actually + meaningful. :Process Time: - Time elapsed since the process began. It is typically measured in rather than , and typically does not advance while the - process is suspended. + Time elapsed since the process began. It is typically measured in + rather than , and typically does not advance + while the process is suspended. :Real Time: - Time in the real world. This differs from in that it is not - , but they should otherwise advance in lockstep. It is not - related to the "real time" of "Real Time [Operating] Systems". It is - sometimes called "wall clock time" to avoid that ambiguity; unfortunately, - that introduces different ambiguities. + Time in the real world. This differs from in that it + is not , but they should otherwise advance in lockstep. + It is not related to the "real time" of "Real Time [Operating] + Systems". It is sometimes called "wall clock time" to avoid that + ambiguity; unfortunately, that introduces different ambiguities. :Resolution: - Represented Digits. Note that many clocks will have a resolution greater - than their actual . + Represented Digits. Note that many clocks will have a resolution + greater than their actual . :Slew: - A slight change to a clock's speed, usually intended to correct with - respect to an external authority. + A slight change to a clock's speed, usually intended to correct + with respect to an external authority. :Stability: Persistence of accuracy. A measure of expected . :Steady: A clock with high and relatively high and - . In practice, it is often used to indicate a - clock, but places greater emphasis on the consistency of the duration - between subsequent ticks. + . In practice, it is often used to indicate a + clock, but places greater emphasis on the + consistency of the duration between subsequent ticks. :Step: - An instantaneous change in the represented time. Instead of speeding or - slowing the clock (), a single offset is permanently added. + An instantaneous change in the represented time. Instead of + speeding or slowing the clock (), a single offset is + permanently added. :System Time: Time as represented by the Operating System. :Thread Time: - Time elapsed since the thread began. It is typically measured in - rather than , and typically does not advance while the thread is - idle. + Time elapsed since the thread began. It is typically measured in + rather than , and typically does not advance + while the thread is idle. :Wallclock: - What the clock on the wall says. This is typically used as a synonym for - ; unfortunately, wall time is itself ambiguous. + What the clock on the wall says. This is typically used as a + synonym for ; unfortunately, wall time is itself + ambiguous. Hardware clocks @@ -471,25 +490,28 @@ List of hardware clocks ----------------------- -* HPET: An High Precision Event Timer (HPET) chip consists of a 64-bit up-counter (main counter) - counting at least at 10 MHz and a set of up to 256 comparators (at - least 3). Each HPET can have up to 32 timers. HPET can cause around 3 seconds of drift per day. -* TSC (Time Stamp Counter): Historically, the TSC increased with every internal - processor clock cycle, but now the rate is usually constant (even if the - processor changes frequency) and usually equals the maximum processor - frequency. Multiple cores having different TSC values. Hibernation of system - will reset TSC value. The RDTSC instruction can be used to read this counter. - CPU frequency scaling for power saving. -* ACPI Power Management Timer: ACPI 24-bit timer with a frequency - of 3.5 MHz (3,579,545 Hz). +* HPET: An High Precision Event Timer (HPET) chip consists of a 64-bit + up-counter (main counter) counting at least at 10 MHz and a set of + up to 256 comparators (at least 3). Each HPET can have up to 32 + timers. HPET can cause around 3 seconds of drift per day. +* TSC (Time Stamp Counter): Historically, the TSC increased with every + internal processor clock cycle, but now the rate is usually constant + (even if the processor changes frequency) and usually equals the + maximum processor frequency. Multiple cores having different TSC + values. Hibernation of system will reset TSC value. The RDTSC + instruction can be used to read this counter. CPU frequency scaling + for power saving. +* ACPI Power Management Timer: ACPI 24-bit timer with a frequency of + 3.5 MHz (3,579,545 Hz). * Cyclone: The Cyclone timer uses a 32-bit counter on IBM Extended X-Architecture (EXA) chipsets which include computers that use the IBM "Summit" series chipsets (ex: x440). This is available in IA32 and IA64 architectures. * PIT (programmable interrupt timer): Intel 8253/8254 chipsets with a - configurable frequency in range 18.2 Hz - 1.2 MHz. It is a 16-bit counter. -* RTC (Real-time clock). Most RTCs use a crystal oscillator with a frequency of - 32,768 Hz + configurable frequency in range 18.2 Hz - 1.2 MHz. It is a 16-bit + counter. +* RTC (Real-time clock). Most RTCs use a crystal oscillator with a + frequency of 32,768 Hz Linux clocksource @@ -516,14 +538,15 @@ architectures. They are at least provided on x86/x86_64, ARM and PowerPC. -The /sys/devices/system/clocksource/clocksource0 directory contains two useful files: +The ``/sys/devices/system/clocksource/clocksource0`` directory +contains two useful files: - * available_clocksource: list of available clock sources - * current_clocksource: clock source currently used. It is possible to change - the current clocksource by writing the name of a clocksource into this - file. +* ``available_clocksource``: list of available clock sources +* ``current_clocksource``: clock source currently used. It is + possible to change the current clocksource by writing the name of a + clocksource into this file. -/proc/timer_list contains the list of all hardware timers. +``/proc/timer_list`` contains the list of all hardware timers. Read also the `time(7) manual page `_: @@ -533,10 +556,11 @@ FreeBSD timecounter ------------------- -kern.timecounter.choice list available hardward clocks with their priority. -The sysctl program can be used to change the timecounter. Example:: +kern.timecounter.choice list available hardware clocks with their +priority. The sysctl program can be used to change the timecounter. +Example:: - # dmesg|grep Timecounter + # dmesg | grep Timecounter Timecounter "i8254" frequency 1193182 Hz quality 0 Timecounter "ACPI-safe" frequency 3579545 Hz quality 850 Timecounter "HPET" frequency 100000000 Hz quality 900 @@ -549,29 +573,29 @@ Available clocks: - * "TSC": Time Stamp Counter of the procesor - * "HPET": High Precision Event Timer - * "ACPI-fast": ACPI Power Management timer (fast mode) - * "ACPI-safe": ACPI Power Management timer (safe mode) - * "i8254": PIT with Intel 8254 chipset +* "TSC": Time Stamp Counter of the processor +* "HPET": High Precision Event Timer +* "ACPI-fast": ACPI Power Management timer (fast mode) +* "ACPI-safe": ACPI Power Management timer (safe mode) +* "i8254": PIT with Intel 8254 chipset The `commit 222222 -`_ (May 2011) -decreased ACPI-fast timecounter quality to 900 and increased HPET timecounter -quality to 950: "HPET on modern platforms usually have better resolution and -lower latency than ACPI timer". +`_ (May +2011) decreased ACPI-fast timecounter quality to 900 and increased +HPET timecounter quality to 950: "HPET on modern platforms usually +have better resolution and lower latency than ACPI timer". Read `Timecounters: Efficient and precise timekeeping in SMP kernels -`_ by Poul-Henning Kamp (2002) for -the FreeBSD Project. +`_ by Poul-Henning Kamp +(2002) for the FreeBSD Project. -Performances ------------- +Performance +----------- -Reading an hardware clock has a cost. The following table compares the -performance of different hardware clocks on Linux 3.3 with Intel Core i7-2600 -at 3.40GHz (8 cores). +Reading an hardware clock has a cost. The following table compares +the performance of different hardware clocks on Linux 3.3 with Intel +Core i7-2600 at 3.40GHz (8 cores). ======================== ====== ======= ====== Function TSC ACPI PM HPET @@ -588,9 +612,9 @@ CLOCK_MONOTONIC 27 ns 723 ns 635 ns ======================== ====== ======= ====== -Each function was called 10,000,000 times and CLOCK_MONOTONIC was used to get -the time before and after. The benchmark was run 5 times to keep the minimum -time. +Each function was called 10,000,000 times and CLOCK_MONOTONIC was used +to get the time before and after. The benchmark was run 5 times to +keep the minimum time. FreeBSD 8.0 in kvm with hardware virtualization: @@ -615,33 +639,34 @@ CLOCK_MONOTONIC 201 ns 10766 ns 4498 ns 3943 ns ======================== ====== ========= ======= ======= -Each function was called 100,000 times and CLOCK_MONOTONIC was used to get -the time before and after. The benchmark was run 5 times to keep the minimum -time. - +Each function was called 100,000 times and CLOCK_MONOTONIC was used to +get the time before and after. The benchmark was run 5 times to keep +the minimum time. NTP adjustment ============== -NTP has diffent methods to adjust a clock: +NTP has different methods to adjust a clock: - * "slewing": change the clock frequency to be slightly faster or slower - (which is done with adjtime()). Since the slew rate is limited to 0.5 ms/s, - each second of adjustment requires an amortization interval of 2000 s. Thus, - an adjustment of many seconds can take hours or days to amortize. - * "stepping": jump by a large amount in a single discrete step (which is done - with settimeofday()) +* "slewing": change the clock frequency to be slightly faster or + slower (which is done with ``adjtime()``). Since the slew rate is + limited to 0.5 ms/s, each second of adjustment requires an + amortization interval of 2000 s. Thus, an adjustment of many + seconds can take hours or days to amortize. +* "stepping": jump by a large amount in a single discrete step (which + is done with ``settimeofday()``) -By default, the time is slewed if the offset is less than 128 ms, or stepped -otherwise. +By default, the time is slewed if the offset is less than 128 ms, or +stepped otherwise. -Slewing is generally desirable (i.e. we should use CLOCK_MONOTONIC, not -CLOCK_MONOTONIC_RAW) if one wishes to measure "real" time (and not a time-like -object like CPU cycles). This is because the clock on the other end of the NTP -connection from you is probably better at keeping time: hopefully that thirty -five thousand dollars of Cesium timekeeping goodness is doing something better -than your PC's $3 quartz crystal, after all. +Slewing is generally desirable (i.e. we should use CLOCK_MONOTONIC, +not CLOCK_MONOTONIC_RAW) if one wishes to measure "real" time (and not +a time-like object like CPU cycles). This is because the clock on the +other end of the NTP connection from you is probably better at keeping +time: hopefully that thirty five thousand dollars of Cesium +timekeeping goodness is doing something better than your PC's $3 +quartz crystal, after all. Get more detail in the `documentation of the NTP daemon `_. @@ -682,10 +707,9 @@ GetTickCount Windows Seven 15.6 ms ========================= ================ =============== -For CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW, the precision of this table is the -result of clock_getres(). It looks like Linux does not implement -clock_getres() and always return 1 nanosecond. - +For CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW, the precision of this +table is the result of ``clock_getres()``. It looks like Linux does +not implement ``clock_getres()`` and always returns 1 nanosecond. mach_absolute_time ^^^^^^^^^^^^^^^^^^ @@ -697,8 +721,8 @@ mach_timebase_info() gives a fraction to convert the clock value to a number of nanoseconds. According to the documentation (`Technical Q&A QA1398 `_), -mach_timebase_info() is always equal to one and never fails, even -if the function may fail according to its prototype. +mach_timebase_info() is always equal to one and never fails, even if +the function may fail according to its prototype. mach_absolute_time() stops during a sleep on a PowerPC CPU, but not on an Intel CPU: `Different behaviour of mach_absolute_time() on i386/ppc @@ -720,7 +744,8 @@ * `Linux clock_gettime() manual page `_ -CLOCK_MONOTONIC is available at least on the following operating systems: +CLOCK_MONOTONIC is available at least on the following operating +systems: * DragonFly BSD, FreeBSD >= 5.0, OpenBSD, NetBSD * Linux @@ -736,30 +761,29 @@ On Linux, NTP may adjust the CLOCK_MONOTONIC rate (slewed), but it cannot jump backward. -CLOCK_MONOTONIC_RAW is specific to Linux. It is similar to CLOCK_MONOTONIC, but -provides access to a raw hardware-based time that is not subject to NTP -adjustments. CLOCK_MONOTONIC_RAW requires Linux 2.6.28 or later. +CLOCK_MONOTONIC_RAW is specific to Linux. It is similar to +CLOCK_MONOTONIC, but provides access to a raw hardware-based time that +is not subject to NTP adjustments. CLOCK_MONOTONIC_RAW requires Linux +2.6.28 or later. CLOCK_MONOTONIC stops while the machine is suspended. -clock_gettime() fails if the system does not support the specified +``clock_gettime()`` fails if the system does not support the specified clock, even if the standard C library supports it. For example, CLOCK_MONOTONIC_RAW requires a kernel version 2.6.28 or later. -clock_getres() gives the clock resolution. It is 1 nanosecond on +``clock_getres()`` gives the clock resolution. It is 1 nanosecond on Linux. .. note:: - clock_gettime() requires to link the program against the rt + ``clock_gettime()`` requires to link the program against the rt (real-time) library. .. note:: - Linux provides also CLOCK_MONOTONIC_COARSE since Linux 2.6.32 which has less - accurate than CLOCK_MONOTONIC but is faster. - - + Linux provides also CLOCK_MONOTONIC_COARSE since Linux 2.6.32 which + has less accuracy than CLOCK_MONOTONIC but is faster. Windows: QueryPerformanceCounter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -767,9 +791,9 @@ High-resolution performance counter. It is monotonic. QueryPerformanceFrequency() gives its frequency. -It has a much higher resolution, but has lower long term precision than -GetTickCount() and timeGetTime() clocks. For example, it will drift -compared to the low precision clocks. +It has a much higher resolution, but has lower long term precision +than GetTickCount() and timeGetTime() clocks. For example, it will +drift compared to the low precision clocks. Documentation: @@ -812,11 +836,11 @@ * Windows XP had a bug (see `KB896256`_): on a multiprocessor computer, QueryPerformanceCounter() returned a different value for each processor. The bug was fixed in Windows XP SP2. -* Issues with processor with variable frequency: the frequency is changed - depending on the workload to reduce memory consumption. -* Chromium don't use QueryPerformanceCounter() on Athlon X2 CPUs (model 15) - because "QueryPerformanceCounter is unreliable" (see base/time_win.cc in - Chromium source code) +* Issues with processor with variable frequency: the frequency is + changed depending on the workload to reduce memory consumption. +* Chromium don't use QueryPerformanceCounter() on Athlon X2 CPUs + (model 15) because "QueryPerformanceCounter is unreliable" (see + base/time_win.cc in Chromium source code) .. _KB896256: http://support.microsoft.com/?id=896256 .. _KB274323: http://support.microsoft.com/?id=274323 @@ -837,15 +861,15 @@ GetTickCount64() was added to Windows Vista and Windows Server 2008. -The clock resolution is 1 millisecond. Its precision is usually around -15 ms. It is possible to improve the precision using the `undocumented -NtSetTimerResolution() function +The clock resolution is 1 millisecond. Its precision is usually +around 15 ms. It is possible to improve the precision using the +`undocumented NtSetTimerResolution() function `_. There are applications using this undocumented function, example: `Timer Resolution `_. -WaitForSingleObject() use the same timer than GetTickCount() with the same -resolution. +WaitForSingleObject() uses the same timer as GetTickCount() with the +same resolution. GetTickCount() has an precision of 55 ms on Windows 9x. @@ -862,16 +886,17 @@ GetTickCount(), timeGetTime() rolls over after 2^32 milliseconds (49.7 days). -The elapsed time retrieved by timeGetTime() includes time the system spends in -sleep. +The elapsed time retrieved by timeGetTime() includes time the system +spends in sleep. The default precision of the timeGetTime function can be five milliseconds or more, depending on the machine. -timeBeginPeriod() can be used to increase the precision of timeGetTime() up to -1 millisecond, but it negatively affects power consumption. Calling -timeBeginPeriod() also affects the granularity of some other timing calls, such -as CreateWaitableTimer(), WaitForSingleObject() and Sleep(). +timeBeginPeriod() can be used to increase the precision of +timeGetTime() up to 1 millisecond, but it negatively affects power +consumption. Calling timeBeginPeriod() also affects the granularity +of some other timing calls, such as CreateWaitableTimer(), +WaitForSingleObject() and Sleep(). .. note:: @@ -879,7 +904,6 @@ library and so require to link the program against winmm or to dynamically load the library. - Solaris: CLOCK_HIGHRES ^^^^^^^^^^^^^^^^^^^^^^ @@ -899,9 +923,8 @@ settimeofday(). The hires timer is ideally suited to performance measurement tasks, where cheap, accurate interval timing is required. -The linearity of gethrtime() is not preserved accross cpr -suspend-resume cycle (`Bug 4272663 -`_). +The linearity of gethrtime() is not preserved across a suspend-resume +cycle (`Bug 4272663 `_). Read the `gethrtime() manual page of Solaris 11 `_. @@ -934,14 +957,14 @@ GetSystemTimeAsFileTime Windows Seven 15.6 ms ========================= ================ =============== -For CLOCK_REALTIME, the precision of this table is the result of clock_getres(). -It looks like Linux does not implement clock_getres() and always return 1 -nanosecond. +For CLOCK_REALTIME, the precision of this table is the result of +clock_getres(). It looks like Linux does not implement clock_getres() +and always returns 1 nanosecond. .. note:: - Linux provides also CLOCK_REALTIME_COARSE since Linux 2.6.32 which has less - accurate than CLOCK_REALTIME but is faster. + Linux provides also CLOCK_REALTIME_COARSE since Linux 2.6.32 which + has less accurate than CLOCK_REALTIME but is faster. Windows: GetSystemTimeAsFileTime @@ -983,8 +1006,8 @@ Process time ------------ -The process time cannot be set. It is not monotonic: the clocks stop while the -process is idle. +The process time cannot be set. It is not monotonic: the clocks stop +while the process is idle. ========================= =============== ============= Name Resolution Include sleep @@ -1009,10 +1032,11 @@ GetProcessTimes() Windows Seven 15.6 ms ========================= ================ =============== -The precision of clock() in this table is the result of 1 / CLOCKS_PER_SEC. -For CLOCK_PROCESS_CPUTIME_ID, the precision of this table is the result of -clock_getres(). It looks like Linux does not implement clock_getres() and -always return 1 nanosecond. For GetProcessTimes(), the precision is read using +The precision of clock() in this table is the result of 1 / +CLOCKS_PER_SEC. For CLOCK_PROCESS_CPUTIME_ID, the precision of this +table is the result of clock_getres(). It looks like Linux does not +implement clock_getres() and always returns 1 nanosecond. For +GetProcessTimes(), the precision is read using GetSystemTimeAdjustment(). @@ -1048,8 +1072,8 @@ Thread time ----------- -The thread time cannot be set. It is not monotonic: the clocks stop while the -thread is idle. +The thread time cannot be set. It is not monotonic: the clocks stop +while the thread is idle. ========================= =============== Name Resolution @@ -1068,10 +1092,10 @@ GetThreadTimes() Windows Seven 15.6 ms ========================= ================ =============== -For CLOCK_THREAD_CPUTIME_ID, the precision of this table is the result of -clock_getres(). It looks like Linux does not implement clock_getres() and -always return 1 nanosecond. For GetThreadTimes(), the precision is read using -GetSystemTimeAdjustment(). +For CLOCK_THREAD_CPUTIME_ID, the precision of this table is the result +of clock_getres(). It looks like Linux does not implement +clock_getres() and always return 1 nanosecond. For GetThreadTimes(), +the precision is read using GetSystemTimeAdjustment(). Functions ^^^^^^^^^ @@ -1110,31 +1134,32 @@ sleep() is not affected by system clock update. -On Linux, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW includes time the system -spends in sleep; but it does not include time spent in hibernation (ACPI S3 -mode). If the system clock jumps backward, CLOCK_MONOTONIC and -CLOCK_MONOTONIC_RAW are not affected. +On Linux, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW includes time the +system spends in sleep; but it does not include time spent in +hibernation (ACPI S3 mode). If the system clock jumps backward, +CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW are not affected. Linux 2.6.39 and glibc 2.14 introduces a new clock: CLOCK_BOOTTIME. -CLOCK_BOOTTIME is idential to CLOCK_MONOTONIC, except it also includes any time -spent in suspend. Read also `Waking systems from suspend -`_ (March, 2011). +CLOCK_BOOTTIME is idential to CLOCK_MONOTONIC, except that it also +includes any time spent in suspend. Read also `Waking systems from +suspend `_ (March, 2011). Other operating systems ----------------------- -On Windows, GetTickCount() and GetTickCount64() include time the system -spends in sleep; sleep() is not affected by system clock update. +On Windows, GetTickCount() and GetTickCount64() include time the +system spends in sleep; sleep() is not affected by system clock +update. -On FreeBSD 8, CLOCK_MONOTONIC include time the system spends in sleep; sleep() -is not affected by system clock update. - -On OpenIndiana, CLOCK_MONOTONIC include time the system spends in sleep; +On FreeBSD 8, CLOCK_MONOTONIC include time the system spends in sleep; sleep() is not affected by system clock update. -On Mac OS X, mach_absolute_time() include time the system spends in sleep; -sleep() is not affected by system clock update. Sleep is interrupted during -suspend. +On OpenIndiana, CLOCK_MONOTONIC include time the system spends in +sleep; sleep() is not affected by system clock update. + +On Mac OS X, mach_absolute_time() include time the system spends in +sleep; sleep() is not affected by system clock update. Sleep is +interrupted during suspend. Sleeping @@ -1181,18 +1206,18 @@ clock_nanosleep --------------- -clock_nanosleep(clock_id, flags, nanoseconds, remaining): -`Linux manpage of clock_nanosleep() +clock_nanosleep(clock_id, flags, nanoseconds, remaining): `Linux +manpage of clock_nanosleep() `_. If flags is TIMER_ABSTIME, then request is interpreted as an absolute time as measured by the clock, clock_id. If request is less than or -equal to the current value of the clock, then clock_nanosleep() returns -immediately without suspending the calling thread. +equal to the current value of the clock, then clock_nanosleep() +returns immediately without suspending the calling thread. -POSIX.1 specifies that changing the value of the CLOCK_REALTIME clock via -clock_settime(2) shall have no effect on a thread that is blocked on a relative -clock_nanosleep(). +POSIX.1 specifies that changing the value of the CLOCK_REALTIME clock +via clock_settime(2) shall have no effect on a thread that is blocked +on a relative clock_nanosleep(). select() @@ -1200,31 +1225,31 @@ select(nfds, readfds, writefds, exceptfs, timeout). -Since Linux 2.6.28, select() uses high-resolution timers to handle the timeout. -A process has a "slack" attribute to configure the precision of the timeout, the -default slack is 50 microseconds. Before Linux 2.6.28, timeouts for select() -were handled by the main timing subsystem at a jiffy-level resolution. Read -also `High- (but not too high-) resolution timeouts -`_ and `Timer slack -`_. +Since Linux 2.6.28, select() uses high-resolution timers to handle the +timeout. A process has a "slack" attribute to configure the precision +of the timeout, the default slack is 50 microseconds. Before Linux +2.6.28, timeouts for select() were handled by the main timing +subsystem at a jiffy-level resolution. Read also `High- (but not too +high-) resolution timeouts `_ and +`Timer slack `_. Other functions --------------- * poll(), epoll() - * sigtimedwait(). POSIX: "If the Monotonic Clock option is supported, the - CLOCK_MONOTONIC clock shall be used to measure the time interval specified - by the timeout argument." - * pthread_cond_timedwait(), pthread_condattr_setclock(). "The default value of - the clock attribute shall refer to the system clock." - * sem_timedwait(): "If the Timers option is supported, the timeout shall be - based on the CLOCK_REALTIME clock. If the Timers option is not supported, - the timeout shall be based on the system clock as returned by the time() - function. The resolution of the timeout shall be the resolution of the clock - on which it is based." - * WaitForSingleObject(): use the same timer than GetTickCount() with the same - resolution. + * sigtimedwait(). POSIX: "If the Monotonic Clock option is supported, + the CLOCK_MONOTONIC clock shall be used to measure the time + interval specified by the timeout argument." + * pthread_cond_timedwait(), pthread_condattr_setclock(). "The default + value of the clock attribute shall refer to the system clock." + * sem_timedwait(): "If the Timers option is supported, the timeout + shall be based on the CLOCK_REALTIME clock. If the Timers option is + not supported, the timeout shall be based on the system clock as + returned by the time() function. The resolution of the timeout + shall be the resolution of the clock on which it is based." + * WaitForSingleObject(): use the same timer than GetTickCount() with + the same resolution. Alternatives: API design @@ -1239,11 +1264,12 @@ * time.seconds() * time.steady() * time.timeout_clock() -* time.wallclock(): it is not the system time aka the "wall clock", but - a monotonic clock with an unspecified starting point +* time.wallclock(): it is not the system time aka the "wall clock", + but a monotonic clock with an unspecified starting point -The name "time.try_monotonic()" was also proposed when time.monotonic() was -falling back to the system clock when no monotonic clock was available. +The name "time.try_monotonic()" was also proposed when +time.monotonic() was falling back to the system clock when no +monotonic clock was available. time.perf_counter(): @@ -1255,23 +1281,25 @@ Only expose operating system clocks ----------------------------------- -To not have to define high-level clocks, which is a difficult task, a simpler -approach is to only expose operating system clocks. time.clock_gettime() and -related clock identifiers were already added to Python 3.3 for example. +To not have to define high-level clocks, which is a difficult task, a +simpler approach is to only expose operating system clocks. +time.clock_gettime() and related clock identifiers were already added +to Python 3.3 for example. Fallback to system clock ------------------------ -If no monotonic clock is available, time.monotonic() falls back to the system -clock. +If no monotonic clock is available, time.monotonic() falls back to the +system clock. Issues: - * It is hard to define correctly such function in the documentation: is it - monotonic? is it steady? is it adjusted? - * Some user want to decide what to do when no monotonic clock is available: - use another clock, display an error, or do something else +* It is hard to define correctly such function in the documentation: + is it monotonic? is it steady? is it adjusted? +* Some user want to decide what to do when no monotonic clock is + available: use another clock, display an error, or do something + else? One function choosing the clock from a list of constraints @@ -1279,38 +1307,39 @@ ``time.get_clock(*flags)`` with the following flags: - * time.MONOTONIC: clock cannot go backard - * time.STEADY: clock rate is steady and the clock is not adjusted - * time.HIGHRES: clock with the highest resolutions +* time.MONOTONIC: clock cannot go backward +* time.STEADY: clock rate is steady and the clock is not adjusted +* time.HIGHRES: clock with the highest resolutions -time.get_clock() returns None if the clock is found and so calls can be chained -using the or operator. Example:: +time.get_clock() returns None if the clock is found and so calls can +be chained using the or operator. Example:: - get_time = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time() - t = get_time() + get_time = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time() + t = get_time() Example of flags of system clocks: - * QueryPerformanceCounter: MONOTONIC | HIGHRES - * GetTickCount: MONOTONIC | STEADY - * CLOCK_MONOTONIC: MONOTONIC | STEADY (or only MONOTONIC on Linux) - * CLOCK_MONOTONIC_RAW: MONOTONIC | STEADY - * gettimeofday(): (no flag) +* QueryPerformanceCounter: MONOTONIC | HIGHRES +* GetTickCount: MONOTONIC | STEADY +* CLOCK_MONOTONIC: MONOTONIC | STEADY (or only MONOTONIC on Linux) +* CLOCK_MONOTONIC_RAW: MONOTONIC | STEADY +* gettimeofday(): (no flag) One function with a flag: time.monotonic(fallback=True) ------------------------------------------------------- - * time.monotonic(fallback=True) falls back to the system clock if no monotonic - clock is available or if the monotonic clock failed. - * time.monotonic(fallback=False) raises OSError if monotonic clock fails and - NotImplementedError if the system does not provide a monotonic clock +* time.monotonic(fallback=True) falls back to the system clock if no + monotonic clock is available or if the monotonic clock failed. +* time.monotonic(fallback=False) raises OSError if monotonic clock + fails and NotImplementedError if the system does not provide a + monotonic clock -"A keyword argument that gets passed as a constant in the caller is usually -poor API." +"A keyword argument that gets passed as a constant in the caller is +usually poor API." -Raising NotImplementedError for a function is something uncommon in Python and -should be avoided. +Raising NotImplementedError for a function is something uncommon in +Python and should be avoided. One function, no flag @@ -1343,10 +1372,10 @@ Issues of a hacked monotonic function: - * if the clock is accidentally set forward by an hour and then back - again, you wouldn't have a useful clock for an hour - * the cache is not shared between processes so different processes wouldn't - see the same clock value +* if the clock is accidentally set forward by an hour and then back + again, you wouldn't have a useful clock for an hour +* the cache is not shared between processes so different processes + wouldn't see the same clock value Footnotes -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 19:13:50 2012 From: python-checkins at python.org (charles-francois.natali) Date: Thu, 12 Apr 2012 19:13:50 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NTU3?= =?utf8?q?=3A_Fix_extensions_build_on_HP-UX=2E_Patch_by_Adi_Roiban=2E?= Message-ID: http://hg.python.org/cpython/rev/807f331f973d changeset: 76263:807f331f973d branch: 3.2 parent: 76259:ed5788424c34 user: Charles-Fran?ois Natali date: Thu Apr 12 19:07:25 2012 +0200 summary: Issue #14557: Fix extensions build on HP-UX. Patch by Adi Roiban. files: Misc/ACKS | 1 + Misc/NEWS | 2 ++ setup.py | 4 ++++ 3 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -783,6 +783,7 @@ Mark Roddy Kevin Rodgers Giampaolo Rodola +Adi Roiban Mike Romberg Armin Ronacher Case Roole diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -131,6 +131,8 @@ Build ----- +- Issue #14557: Fix extensions build on HP-UX. Patch by Adi Roiban. + - Issue #14437: Fix building the _io module under Cygwin. - Issue #14387: Do not include accu.h from Python.h. diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -467,6 +467,10 @@ if platform in ['osf1', 'unixware7', 'openunix8']: lib_dirs += ['/usr/ccs/lib'] + # HP-UX11iv3 keeps files in lib/hpux folders. + if platform == 'hp-ux11': + lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32'] + if platform == 'darwin': # This should work on any unixy platform ;-) # If the user has bothered specifying additional -I and -L flags -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 19:13:52 2012 From: python-checkins at python.org (charles-francois.natali) Date: Thu, 12 Apr 2012 19:13:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314557=3A_Fix_extensions_build_on_HP-UX=2E_Patch_by_?= =?utf8?q?Adi_Roiban=2E?= Message-ID: http://hg.python.org/cpython/rev/9481e801ae7c changeset: 76264:9481e801ae7c parent: 76262:0f114b855824 parent: 76263:807f331f973d user: Charles-Fran?ois Natali date: Thu Apr 12 19:09:00 2012 +0200 summary: Issue #14557: Fix extensions build on HP-UX. Patch by Adi Roiban. files: Misc/ACKS | 1 + Misc/NEWS | 2 ++ setup.py | 4 ++++ 3 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -862,6 +862,7 @@ Kevin Rodgers Giampaolo Rodola Elson Rodriguez +Adi Roiban Luis Rojas Mike Romberg Armin Ronacher diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -264,6 +264,8 @@ Build ----- +- Issue #14557: Fix extensions build on HP-UX. Patch by Adi Roiban. + - Issue #14387: Do not include accu.h from Python.h. - Issue #14359: Only use O_CLOEXEC in _posixmodule.c if it is defined. diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -464,6 +464,10 @@ if platform in ['osf1', 'unixware7', 'openunix8']: lib_dirs += ['/usr/ccs/lib'] + # HP-UX11iv3 keeps files in lib/hpux folders. + if platform == 'hp-ux11': + lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32'] + if platform == 'darwin': # This should work on any unixy platform ;-) # If the user has bothered specifying additional -I and -L flags -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 19:13:54 2012 From: python-checkins at python.org (charles-francois.natali) Date: Thu, 12 Apr 2012 19:13:54 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NTU3?= =?utf8?q?=3A_Fix_extensions_build_on_HP-UX=2E_Patch_by_Adi_Roiban=2E?= Message-ID: http://hg.python.org/cpython/rev/cc2e3c6d2669 changeset: 76265:cc2e3c6d2669 branch: 2.7 parent: 76261:d60ef141e090 user: Charles-Fran?ois Natali date: Thu Apr 12 19:11:54 2012 +0200 summary: Issue #14557: Fix extensions build on HP-UX. Patch by Adi Roiban. files: Misc/ACKS | 1 + Misc/NEWS | 2 ++ setup.py | 4 ++++ 3 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -717,6 +717,7 @@ Andy Robinson Kevin Rodgers Giampaolo Rodola +Adi Roiban Mike Romberg Armin Ronacher Case Roole diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -94,6 +94,8 @@ Build ----- +- Issue #14557: Fix extensions build on HP-UX. Patch by Adi Roiban. + - Issue #14437: Fix building the _io module under Cygwin. diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -451,6 +451,10 @@ if platform in ['osf1', 'unixware7', 'openunix8']: lib_dirs += ['/usr/ccs/lib'] + # HP-UX11iv3 keeps files in lib/hpux folders. + if platform == 'hp-ux11': + lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32'] + if platform == 'darwin': # This should work on any unixy platform ;-) # If the user has bothered specifying additional -I and -L flags -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 19:41:54 2012 From: python-checkins at python.org (georg.brandl) Date: Thu, 12 Apr 2012 19:41:54 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogMy4yIHNpZGViYXI6?= =?utf8?q?_link_to_3=2E3=2C_not_3=2E1?= Message-ID: http://hg.python.org/cpython/rev/427c4a63724e changeset: 76266:427c4a63724e branch: 3.2 parent: 76263:807f331f973d user: Georg Brandl date: Thu Apr 12 19:41:10 2012 +0200 summary: 3.2 sidebar: link to 3.3, not 3.1 files: Doc/tools/sphinxext/indexsidebar.html | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/sphinxext/indexsidebar.html b/Doc/tools/sphinxext/indexsidebar.html --- a/Doc/tools/sphinxext/indexsidebar.html +++ b/Doc/tools/sphinxext/indexsidebar.html @@ -3,7 +3,7 @@

Docs for other versions

-- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 19:41:55 2012 From: python-checkins at python.org (georg.brandl) Date: Thu, 12 Apr 2012 19:41:55 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Null-merge_3=2E2_branch=2E?= Message-ID: http://hg.python.org/cpython/rev/37c500ee609a changeset: 76267:37c500ee609a parent: 76264:9481e801ae7c parent: 76266:427c4a63724e user: Georg Brandl date: Thu Apr 12 19:41:50 2012 +0200 summary: Null-merge 3.2 branch. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 21:51:51 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 21:51:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Doc=3A_sort_time=2ECLOCK=5F?= =?utf8?q?xxx_constants?= Message-ID: http://hg.python.org/cpython/rev/3df2f4a83816 changeset: 76268:3df2f4a83816 user: Victor Stinner date: Thu Apr 12 21:40:14 2012 +0200 summary: Doc: sort time.CLOCK_xxx constants files: Doc/library/time.rst | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -158,14 +158,6 @@ .. versionadded:: 3.3 -.. data:: CLOCK_REALTIME - - System-wide real-time clock. Setting this clock requires appropriate - privileges. - - .. versionadded:: 3.3 - - .. data:: CLOCK_HIGHRES The Solaris OS has a CLOCK_HIGHRES timer that attempts to use an optimal @@ -200,6 +192,14 @@ .. versionadded:: 3.3 +.. data:: CLOCK_REALTIME + + System-wide real-time clock. Setting this clock requires appropriate + privileges. + + .. versionadded:: 3.3 + + .. data:: CLOCK_THREAD_CPUTIME_ID Thread-specific CPU-time clock. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 12 22:27:16 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 22:27:16 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PeP_418=3A_Move_the_CLOCK=5FBO?= =?utf8?q?OTTIME_paragraph?= Message-ID: http://hg.python.org/peps/rev/1259bf33675d changeset: 4234:1259bf33675d user: Victor Stinner date: Thu Apr 12 22:26:43 2012 +0200 summary: PeP 418: Move the CLOCK_BOOTTIME paragraph files: pep-0418.txt | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -730,8 +730,8 @@ mach_absolute_time() has a resolution of 1 nanosecond. -CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW, CLOCK_BOOTTIME +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW represent monotonic time since some unspecified starting point. They cannot be set. @@ -766,6 +766,11 @@ is not subject to NTP adjustments. CLOCK_MONOTONIC_RAW requires Linux 2.6.28 or later. +Linux 2.6.39 and glibc 2.14 introduces a new clock: CLOCK_BOOTTIME. +CLOCK_BOOTTIME is idential to CLOCK_MONOTONIC, except that it also +includes any time spent in suspend. Read also `Waking systems from +suspend `_ (March, 2011). + CLOCK_MONOTONIC stops while the machine is suspended. ``clock_gettime()`` fails if the system does not support the specified @@ -1139,11 +1144,6 @@ hibernation (ACPI S3 mode). If the system clock jumps backward, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW are not affected. -Linux 2.6.39 and glibc 2.14 introduces a new clock: CLOCK_BOOTTIME. -CLOCK_BOOTTIME is idential to CLOCK_MONOTONIC, except that it also -includes any time spent in suspend. Read also `Waking systems from -suspend `_ (March, 2011). - Other operating systems ----------------------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 22:42:45 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 22:42:45 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_On_Windows=2C_clock?= =?utf8?q?=28=29_does_include_time_elapsed_during_a_sleep?= Message-ID: http://hg.python.org/peps/rev/306517a9822b changeset: 4235:306517a9822b user: Victor Stinner date: Thu Apr 12 22:42:11 2012 +0200 summary: PEP 418: On Windows, clock() does include time elapsed during a sleep files: pep-0418.txt | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1020,9 +1020,12 @@ GetProcessTimes() 100 ns No CLOCK_PROCESS_CPUTIME_ID 1 ns No getrusage() 1 ?s No -clock() \- No +clock() \- No (*) ========================= =============== ============= +(*) On Windows, clock() does include time elapsed during a sleep. It does not +on other operating systems. + Examples of clock precision on x86_64: ========================= ================ =============== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 12 22:43:28 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 12 Apr 2012 22:43:28 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_fix_typo_=28some_?= =?utf8?b?PT4gc3VtKQ==?= Message-ID: http://hg.python.org/peps/rev/193f765deba8 changeset: 4236:193f765deba8 user: Victor Stinner date: Thu Apr 12 22:42:54 2012 +0200 summary: PEP 418: fix typo (some => sum) files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -200,7 +200,7 @@ time.process_time() ^^^^^^^^^^^^^^^^^^^ -Process time used for profiling: some of kernel and user-space CPU +Process time used for profiling: sum of the kernel and user-space CPU time. It does not include time elapsed during sleep. The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 13 00:00:13 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 13 Apr 2012 00:00:13 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_info_on_notific?= =?utf8?q?ation_of_system_power_state_changes?= Message-ID: http://hg.python.org/peps/rev/1e585cd8a059 changeset: 4237:1e585cd8a059 user: Victor Stinner date: Thu Apr 12 23:56:58 2012 +0200 summary: PEP 418: Add info on notification of system power state changes files: pep-0418.txt | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1007,6 +1007,11 @@ The system time can be set using settimeofday() or clock_settime(CLOCK_REALTIME). +Alexander Shishkin proposed an API for Linux to be notified when the system +clock is changed: `timerfd: add TFD_NOTIFY_CLOCK_SET to watch for clock changes +`_ (4th version of the API, March 2011). The +API is not accepted yet, CLOCK_BOOTTIME provides a similar feature. + Process time ------------ @@ -1150,9 +1155,10 @@ Other operating systems ----------------------- -On Windows, GetTickCount() and GetTickCount64() include time the -system spends in sleep; sleep() is not affected by system clock -update. +On Windows, GetTickCount() and GetTickCount64() include time the system spends +in sleep; sleep() is not affected by system clock update. The WM_POWERBROADCAST +message is send to Windows application to notify them of power-management +events (ex: ower status has changed). On FreeBSD 8, CLOCK_MONOTONIC include time the system spends in sleep; sleep() is not affected by system clock update. @@ -1162,7 +1168,10 @@ On Mac OS X, mach_absolute_time() include time the system spends in sleep; sleep() is not affected by system clock update. Sleep is -interrupted during suspend. +interrupted during suspend. Read also: `Registering and unregistering for sleep +and wake notifications +`_ (Technical +Q&A QA1340). Sleeping -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 13 00:45:15 2012 From: python-checkins at python.org (r.david.murray) Date: Fri, 13 Apr 2012 00:45:15 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0Mzk5OiB6aXBm?= =?utf8?q?ile_now_correctly_handles_comments_added_to_empty_zipfiles=2E?= Message-ID: http://hg.python.org/cpython/rev/ac0ec1f31b0a changeset: 76269:ac0ec1f31b0a branch: 2.7 parent: 76265:cc2e3c6d2669 user: R David Murray date: Thu Apr 12 18:42:47 2012 -0400 summary: #14399: zipfile now correctly handles comments added to empty zipfiles. Patch by Serhiy Storchaka. files: Lib/test/test_zipfile.py | 16 +++++++++++++ Lib/zipfile.py | 33 +++++++++++++++++---------- Misc/ACKS | 1 + Misc/NEWS | 4 +++ 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -908,6 +908,22 @@ with zipfile.ZipFile(TESTFN, mode="r") as zipf: self.assertEqual(zipf.comment, comment2) + def test_change_comment_in_empty_archive(self): + with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: + self.assertFalse(zipf.filelist) + zipf.comment = b"this is a comment" + with zipfile.ZipFile(TESTFN, "r") as zipf: + self.assertEqual(zipf.comment, b"this is a comment") + + def test_change_comment_in_nonempty_archive(self): + with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: + zipf.writestr("foo.txt", "O, for a Muse of Fire!") + with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: + self.assertTrue(zipf.filelist) + zipf.comment = b"this is a comment" + with zipfile.ZipFile(TESTFN, "r") as zipf: + self.assertEqual(zipf.comment, b"this is a comment") + def check_testzip_with_bad_crc(self, compression): """Tests that files with bad CRCs return their name from testzip.""" zipdata = self.zips_with_bad_crc[compression] diff --git a/Lib/zipfile.py b/Lib/zipfile.py --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -651,7 +651,7 @@ -class ZipFile: +class ZipFile(object): """ Class with methods to open, read, write, close, list zip files. z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False) @@ -690,7 +690,7 @@ self.compression = compression # Method of compression self.mode = key = mode.replace('b', '')[0] self.pwd = None - self.comment = '' + self._comment = '' # Check if we were passed a file-like object if isinstance(file, basestring): @@ -765,7 +765,7 @@ print endrec size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory - self.comment = endrec[_ECD_COMMENT] # archive comment + self._comment = endrec[_ECD_COMMENT] # archive comment # "concat" is zero, unless zip was concatenated to another file concat = endrec[_ECD_LOCATION] - size_cd - offset_cd @@ -864,6 +864,22 @@ """Set default password for encrypted files.""" self.pwd = pwd + @property + def comment(self): + """The comment text associated with the ZIP file.""" + return self._comment + + @comment.setter + def comment(self, comment): + # check for valid comment length + if len(comment) >= ZIP_MAX_COMMENT: + if self.debug: + print('Archive comment is too long; truncating to %d bytes' + % ZIP_MAX_COMMENT) + comment = comment[:ZIP_MAX_COMMENT] + self._comment = comment + self._didModify = True + def read(self, name, pwd=None): """Return file bytes (as a string) for name.""" return self.open(name, "r", pwd).read() @@ -1243,18 +1259,11 @@ centDirSize = min(centDirSize, 0xFFFFFFFF) centDirOffset = min(centDirOffset, 0xFFFFFFFF) - # check for valid comment length - if len(self.comment) >= ZIP_MAX_COMMENT: - if self.debug > 0: - msg = 'Archive comment is too long; truncating to %d bytes' \ - % ZIP_MAX_COMMENT - self.comment = self.comment[:ZIP_MAX_COMMENT] - endrec = struct.pack(structEndArchive, stringEndArchive, 0, 0, centDirCount, centDirCount, - centDirSize, centDirOffset, len(self.comment)) + centDirSize, centDirOffset, len(self._comment)) self.fp.write(endrec) - self.fp.write(self.comment) + self.fp.write(self._comment) self.fp.flush() if not self._filePassed: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -814,6 +814,7 @@ Peter Stoehr Casper Stoel Michael Stone +Serhiy Storchaka Ken Stox Patrick Strawderman Dan Stromberg diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -44,6 +44,10 @@ Library ------- +- Issue #14399: zipfile now correctly adds a comment even when the zipfile + being created is otherwise empty. As a consequence of this fix, ZipFile is + now a new style class. + - Issue #7978: SocketServer now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. Patch by Jerzy Kozera. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 00:45:16 2012 From: python-checkins at python.org (r.david.murray) Date: Fri, 13 Apr 2012 00:45:16 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0Mzk5OiB6aXBm?= =?utf8?q?ile_now_correctly_handles_comments_added_to_empty_zipfiles=2E?= Message-ID: http://hg.python.org/cpython/rev/4186f20d9fa4 changeset: 76270:4186f20d9fa4 branch: 3.2 parent: 76266:427c4a63724e user: R David Murray date: Thu Apr 12 18:44:42 2012 -0400 summary: #14399: zipfile now correctly handles comments added to empty zipfiles. Patch by Serhiy Storchaka. This also moves the TypeError that results from trying to use a unicode comment from the 'close' step to the point at which the comment is added to the zipfile. files: Lib/test/test_zipfile.py | 22 ++++++++++++++++++ Lib/zipfile.py | 33 ++++++++++++++++++--------- Misc/ACKS | 1 + Misc/NEWS | 5 ++++ 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -972,6 +972,28 @@ with zipfile.ZipFile(TESTFN, mode="r") as zipfr: self.assertEqual(zipfr.comment, comment2) + def test_unicode_comment(self): + with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: + zipf.writestr("foo.txt", "O, for a Muse of Fire!") + with self.assertRaises(TypeError): + zipf.comment = "this is an error" + + def test_change_comment_in_empty_archive(self): + with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: + self.assertFalse(zipf.filelist) + zipf.comment = b"this is a comment" + with zipfile.ZipFile(TESTFN, "r") as zipf: + self.assertEqual(zipf.comment, b"this is a comment") + + def test_change_comment_in_nonempty_archive(self): + with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: + zipf.writestr("foo.txt", "O, for a Muse of Fire!") + with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: + self.assertTrue(zipf.filelist) + zipf.comment = b"this is a comment" + with zipfile.ZipFile(TESTFN, "r") as zipf: + self.assertEqual(zipf.comment, b"this is a comment") + def check_testzip_with_bad_crc(self, compression): """Tests that files with bad CRCs return their name from testzip.""" zipdata = self.zips_with_bad_crc[compression] diff --git a/Lib/zipfile.py b/Lib/zipfile.py --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -698,7 +698,7 @@ self.compression = compression # Method of compression self.mode = key = mode.replace('b', '')[0] self.pwd = None - self.comment = b'' + self._comment = b'' # Check if we were passed a file-like object if isinstance(file, str): @@ -774,7 +774,7 @@ print(endrec) size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory - self.comment = endrec[_ECD_COMMENT] # archive comment + self._comment = endrec[_ECD_COMMENT] # archive comment # "concat" is zero, unless zip was concatenated to another file concat = endrec[_ECD_LOCATION] - size_cd - offset_cd @@ -886,6 +886,24 @@ else: self.pwd = None + @property + def comment(self): + """The comment text associated with the ZIP file.""" + return self._comment + + @comment.setter + def comment(self, comment): + if not isinstance(comment, bytes): + raise TypeError("comment: expected bytes, got %s" % type(comment)) + # check for valid comment length + if len(comment) >= ZIP_MAX_COMMENT: + if self.debug: + print('Archive comment is too long; truncating to %d bytes' + % ZIP_MAX_COMMENT) + comment = comment[:ZIP_MAX_COMMENT] + self._comment = comment + self._didModify = True + def read(self, name, pwd=None): """Return file bytes (as a string) for name.""" with self.open(name, "r", pwd) as fp: @@ -1287,18 +1305,11 @@ centDirSize = min(centDirSize, 0xFFFFFFFF) centDirOffset = min(centDirOffset, 0xFFFFFFFF) - # check for valid comment length - if len(self.comment) >= ZIP_MAX_COMMENT: - if self.debug > 0: - msg = 'Archive comment is too long; truncating to %d bytes' \ - % ZIP_MAX_COMMENT - self.comment = self.comment[:ZIP_MAX_COMMENT] - endrec = struct.pack(structEndArchive, stringEndArchive, 0, 0, centDirCount, centDirCount, - centDirSize, centDirOffset, len(self.comment)) + centDirSize, centDirOffset, len(self._comment)) self.fp.write(endrec) - self.fp.write(self.comment) + self.fp.write(self._comment) self.fp.flush() if not self._filePassed: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -887,6 +887,7 @@ Peter Stoehr Casper Stoel Michael Stone +Serhiy Storchaka Ken Stox Dan Stromberg Daniel Stutzbach diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,11 @@ Library ------- +- Issue #14399: zipfile now correctly adds a comment even when the zipfile + being created is otherwise empty. In addition, the TypeError that results + from trying to set a non-binary value as a comment is now now raised at the + time the comment is set rather than at the time the zipfile is written. + - Issue #7978: socketserver now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. Patch by Jerzy Kozera. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 00:45:20 2012 From: python-checkins at python.org (r.david.murray) Date: Fri, 13 Apr 2012 00:45:20 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Merge_=2314399=3A_zipfile_n?= =?utf8?q?ow_correctly_handles_comments_added_to_empty_zipfiles=2E?= Message-ID: http://hg.python.org/cpython/rev/e5b30d4b0647 changeset: 76271:e5b30d4b0647 parent: 76268:3df2f4a83816 user: R David Murray date: Thu Apr 12 18:44:58 2012 -0400 summary: Merge #14399: zipfile now correctly handles comments added to empty zipfiles. Patch by Serhiy Storchaka. This also moves the TypeError that results from trying to use a unicode comment from the 'close' step to the point at which the comment is added to the zipfile. files: Lib/test/test_zipfile.py | 22 ++++++++++++++++++ Lib/zipfile.py | 33 ++++++++++++++++++--------- Misc/NEWS | 5 ++++ 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -970,6 +970,28 @@ with zipfile.ZipFile(TESTFN, mode="r") as zipfr: self.assertEqual(zipfr.comment, comment2) + def test_unicode_comment(self): + with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: + zipf.writestr("foo.txt", "O, for a Muse of Fire!") + with self.assertRaises(TypeError): + zipf.comment = "this is an error" + + def test_change_comment_in_empty_archive(self): + with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: + self.assertFalse(zipf.filelist) + zipf.comment = b"this is a comment" + with zipfile.ZipFile(TESTFN, "r") as zipf: + self.assertEqual(zipf.comment, b"this is a comment") + + def test_change_comment_in_nonempty_archive(self): + with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: + zipf.writestr("foo.txt", "O, for a Muse of Fire!") + with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: + self.assertTrue(zipf.filelist) + zipf.comment = b"this is a comment" + with zipfile.ZipFile(TESTFN, "r") as zipf: + self.assertEqual(zipf.comment, b"this is a comment") + def check_testzip_with_bad_crc(self, compression): """Tests that files with bad CRCs return their name from testzip.""" zipdata = self.zips_with_bad_crc[compression] diff --git a/Lib/zipfile.py b/Lib/zipfile.py --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -698,7 +698,7 @@ self.compression = compression # Method of compression self.mode = key = mode.replace('b', '')[0] self.pwd = None - self.comment = b'' + self._comment = b'' # Check if we were passed a file-like object if isinstance(file, str): @@ -774,7 +774,7 @@ print(endrec) size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory - self.comment = endrec[_ECD_COMMENT] # archive comment + self._comment = endrec[_ECD_COMMENT] # archive comment # "concat" is zero, unless zip was concatenated to another file concat = endrec[_ECD_LOCATION] - size_cd - offset_cd @@ -886,6 +886,24 @@ else: self.pwd = None + @property + def comment(self): + """The comment text associated with the ZIP file.""" + return self._comment + + @comment.setter + def comment(self, comment): + if not isinstance(comment, bytes): + raise TypeError("comment: expected bytes, got %s" % type(comment)) + # check for valid comment length + if len(comment) >= ZIP_MAX_COMMENT: + if self.debug: + print('Archive comment is too long; truncating to %d bytes' + % ZIP_MAX_COMMENT) + comment = comment[:ZIP_MAX_COMMENT] + self._comment = comment + self._didModify = True + def read(self, name, pwd=None): """Return file bytes (as a string) for name.""" with self.open(name, "r", pwd) as fp: @@ -1287,18 +1305,11 @@ centDirSize = min(centDirSize, 0xFFFFFFFF) centDirOffset = min(centDirOffset, 0xFFFFFFFF) - # check for valid comment length - if len(self.comment) >= ZIP_MAX_COMMENT: - if self.debug > 0: - msg = 'Archive comment is too long; truncating to %d bytes' \ - % ZIP_MAX_COMMENT - self.comment = self.comment[:ZIP_MAX_COMMENT] - endrec = struct.pack(structEndArchive, stringEndArchive, 0, 0, centDirCount, centDirCount, - centDirSize, centDirOffset, len(self.comment)) + centDirSize, centDirOffset, len(self._comment)) self.fp.write(endrec) - self.fp.write(self.comment) + self.fp.write(self._comment) self.fp.flush() if not self._filePassed: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,11 @@ Library ------- +- Issue #14399: zipfile now correctly adds a comment even when the zipfile + being created is otherwise empty. In addition, the TypeError that results + from trying to set a non-binary value as a comment is now now raised at the + time the comment is set rather than at the time the zipfile is written. + - trace.CoverageResults.is_ignored_filename() now ignores any name that starts with "<" and ends with ">" instead of special-casing "" and " http://hg.python.org/peps/rev/f3202262d285 changeset: 4238:f3202262d285 user: Victor Stinner date: Fri Apr 13 01:21:00 2012 +0200 summary: PEP 418: time.process_time() falls back on other clock instead of falling files: pep-0418.txt | 43 ++++++++++++++++++++++++++------------- 1 files changed, 29 insertions(+), 14 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -205,27 +205,42 @@ point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid. -Pseudo-code:: +Pseudo-code [#pseudo]_:: if os.name == 'nt': def process_time(): handle = win32process.GetCurrentProcess() process_times = win32process.GetProcessTimes(handle) return (process_times['UserTime'] + process_times['KernelTime']) * 1e-7 - elif (hasattr(time, 'clock_gettime') - and hasattr(time, 'CLOCK_PROCESS_CPUTIME_ID')): + else: def process_time(): - return time.clock_gettime(time.CLOCK_PROCESS_CPUTIME_ID) - else: - try: - import resource - except ImportError: - def process_time(): - return _time.clock() - else: - def process_time(): - usage = resource.getrusage(resource.RUSAGE_SELF) - return usage[0] + usage[1] + if process_time.use_process_cputime: + try: + return time.clock_gettime(time.CLOCK_PROCESS_CPUTIME_ID) + except OSError: + process_time.use_process_cputime = False + if process_time.use_getrusage: + if process_time.getrusage is None: + try: + import resource + except ImportError: + process_time.use_getrusage = False + else: + def getrusage(): + usage = resource.getrusage(resource.RUSAGE_SELF) + return usage[0] + usage[1] + process_time.getrusage = getrusage + if process_time.use_getrusage: + try: + return process_time.getrusage() + except OSError: + process_time.use_getrusage = False + return _time.clock() + process_time.use_process_cputime = ( + hasattr(time, 'clock_gettime') + and hasattr(time, 'CLOCK_PROCESS_CPUTIME_ID')) + process_time.use_getrusage = True + process_time.getrusage = None Existing functions -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 13 02:17:45 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 13 Apr 2012 02:17:45 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Remove_duplicate_in?= =?utf8?q?fo_about_clock_resolution?= Message-ID: http://hg.python.org/peps/rev/89f8ecf2d78a changeset: 4239:89f8ecf2d78a user: Victor Stinner date: Fri Apr 13 02:16:55 2012 +0200 summary: PEP 418: Remove duplicate info about clock resolution files: pep-0418.txt | 72 ++++++++++----------------------------- 1 files changed, 19 insertions(+), 53 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -264,23 +264,19 @@ def time(): if hasattr(time, "clock_gettime"): try: - # resolution = 1 nanosecond return time.clock_gettime(time.CLOCK_REALTIME) except OSError: # CLOCK_REALTIME is not supported (unlikely) pass if hasattr(_time, "gettimeofday"): try: - # resolution = 1 microsecond return _time.gettimeofday() except OSError: # gettimeofday() should not fail pass if hasattr(_time, "ftime"): - # resolution = 1 millisecond return _time.ftime() else: - # resolution = 1 second return _time.time() @@ -722,9 +718,9 @@ GetTickCount Windows Seven 15.6 ms ========================= ================ =============== -For CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW, the precision of this -table is the result of ``clock_getres()``. It looks like Linux does -not implement ``clock_getres()`` and always returns 1 nanosecond. +For CLOCK_xxx clocks, the precision of this table is the result of +``clock_getres()``. It looks like Linux does not implement ``clock_getres()`` +and always returns 1 nanosecond. mach_absolute_time ^^^^^^^^^^^^^^^^^^ @@ -743,8 +739,6 @@ an Intel CPU: `Different behaviour of mach_absolute_time() on i386/ppc `_. -mach_absolute_time() has a resolution of 1 nanosecond. - CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW, CLOCK_BOOTTIME ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -792,9 +786,6 @@ clock, even if the standard C library supports it. For example, CLOCK_MONOTONIC_RAW requires a kernel version 2.6.28 or later. -``clock_getres()`` gives the clock resolution. It is 1 nanosecond on -Linux. - .. note:: ``clock_gettime()`` requires to link the program against the rt @@ -881,15 +872,14 @@ GetTickCount64() was added to Windows Vista and Windows Server 2008. -The clock resolution is 1 millisecond. Its precision is usually -around 15 ms. It is possible to improve the precision using the -`undocumented NtSetTimerResolution() function +It is possible to improve the precision using the `undocumented +NtSetTimerResolution() function `_. -There are applications using this undocumented function, example: -`Timer Resolution `_. +There are applications using this undocumented function, example: `Timer +Resolution `_. WaitForSingleObject() uses the same timer as GetTickCount() with the -same resolution. +same precision. GetTickCount() has an precision of 55 ms on Windows 9x. @@ -990,16 +980,9 @@ Windows: GetSystemTimeAsFileTime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The system time can be read using GetSystemTimeAsFileTime(), ftime() -and time(). - -The system time resolution can be read using -GetSystemTimeAdjustment(). The precision is usually between 1 -millisecond and 15 milliseconds. Resolution: - -* GetSystemTimeAsFileTime(): 100 nanoseconds -* ftime(): 1 millisecond -* time(): 1 second +The system time can be read using GetSystemTimeAsFileTime(), ftime() and +time(). The precision of the system clock can be read using +GetSystemTimeAdjustment(). Read the `GetSystemTimeAsFileTime() documentation `_. @@ -1012,13 +995,6 @@ gettimeofday(), ftime(), time() and clock_gettime(CLOCK_REALTIME) return the system clock. -Resolution: - -* clock_gettime(): clock_getres(CLOCK_REALTIME) -* gettimeofday(): 1 microsecond -* ftime(): 1 millisecond -* time(): 1 second - The system time can be set using settimeofday() or clock_settime(CLOCK_REALTIME). @@ -1071,7 +1047,8 @@ Functions ^^^^^^^^^ -* Windows: GetProcessTimes() +* Windows: GetProcessTimes(). The precision can be read using + GetSystemTimeAdjustment(). * clock_gettime(CLOCK_PROCESS_CPUTIME_ID): High-resolution per-process timer from the CPU. * clock(): @@ -1085,13 +1062,6 @@ * times() * getrusage(): ru_utime and ru_stime fields -Resolution: - -* clock() rate is CLOCKS_PER_SEC. It was called CLK_TCK in Microsoft - C before 6.0. -* The clock resolution can be read using clock_getres(). -* GetProcessTimes(): call GetSystemTimeAdjustment(). - Python source code includes a portable library to get the process time (CPU time): `Tools/pybench/systimes.py `_. @@ -1128,15 +1098,11 @@ Functions ^^^^^^^^^ -* Windows: GetThreadTimes() +* Windows: GetThreadTimes(). The precision can be read using + GetSystemTimeAdjustment(). * clock_gettime(CLOCK_THREAD_CPUTIME_ID): Thread-specific CPU-time clock. -Resolution: - -* CLOCK_THREAD_CPUTIME_ID: call clock_getres(). -* GetThreadTimes(): call GetSystemTimeAdjustment() - See also pthread_getcpuclockid(). @@ -1273,10 +1239,10 @@ * sem_timedwait(): "If the Timers option is supported, the timeout shall be based on the CLOCK_REALTIME clock. If the Timers option is not supported, the timeout shall be based on the system clock as - returned by the time() function. The resolution of the timeout - shall be the resolution of the clock on which it is based." + returned by the time() function. The precision of the timeout + shall be the precision of the clock on which it is based." * WaitForSingleObject(): use the same timer than GetTickCount() with - the same resolution. + the same precision. Alternatives: API design @@ -1336,7 +1302,7 @@ * time.MONOTONIC: clock cannot go backward * time.STEADY: clock rate is steady and the clock is not adjusted -* time.HIGHRES: clock with the highest resolutions +* time.HIGHRES: clock with the highest precision time.get_clock() returns None if the clock is found and so calls can be chained using the or operator. Example:: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 13 02:25:13 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 13 Apr 2012 02:25:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=231559549=3A_Add_=27?= =?utf8?q?name=27_and_=27path=27_attributes_to_ImportError=2E?= Message-ID: http://hg.python.org/cpython/rev/6825fd9b00ed changeset: 76272:6825fd9b00ed user: Brett Cannon date: Thu Apr 12 20:24:54 2012 -0400 summary: Issue #1559549: Add 'name' and 'path' attributes to ImportError. Currently import does not use these attributes as they are planned for use by importlib (which will be another commit). Thanks to Filip Gruszczy?ski for the initial patch and Brian Curtin for refining it. files: Doc/library/exceptions.rst | 8 ++ Include/pyerrors.h | 13 +++ Lib/test/test_exceptions.py | 24 +++++- Misc/NEWS | 4 + Objects/exceptions.c | 99 ++++++++++++++++++++++++- Python/errors.c | 47 +++++++++++ 6 files changed, 192 insertions(+), 3 deletions(-) diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -159,6 +159,14 @@ Raised when an :keyword:`import` statement fails to find the module definition or when a ``from ... import`` fails to find a name that is to be imported. + The :attr:`name` and :attr:`path` attributes can be set using keyword-only + arguments to the constructor. When set they represent the name of the module + that was attempted to be imported and the path to any file which triggered + the exception, respectively. + + .. versionchanged:: 3.3 + Added the :attr:`name` and :attr:`path` attributes. + .. exception:: IndexError diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -231,6 +231,13 @@ ... ); +typedef struct { + PyException_HEAD + PyObject *msg; + PyObject *name; + PyObject *path; +} PyImportErrorObject; + #ifdef MS_WINDOWS PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename( int ierr, @@ -256,6 +263,12 @@ PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); #endif /* MS_WINDOWS */ +PyAPI_FUNC(PyObject *) PyErr_SetExcWithArgsKwargs(PyObject *, PyObject *, + PyObject *); +PyAPI_FUNC(PyObject *) PyErr_SetFromImportErrorWithNameAndPath(PyObject *, + PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyErr_SetFromImportErrorWithName(PyObject *, PyObject *); + /* Export the old function so that the existing API remains available: */ PyAPI_FUNC(void) PyErr_BadInternalCall(void); PyAPI_FUNC(void) _PyErr_BadInternalCall(const char *filename, int lineno); diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -902,8 +902,30 @@ self.assertEqual(cm.exception.errno, errno.ENOTDIR, cm.exception) +class ImportErrorTests(unittest.TestCase): + + def test_attributes(self): + # Setting 'name' and 'path' should not be a problem. + exc = ImportError('test') + self.assertIsNone(exc.name) + self.assertIsNone(exc.path) + + exc = ImportError('test', name='somemodule') + self.assertEqual(exc.name, 'somemodule') + self.assertIsNone(exc.path) + + exc = ImportError('test', path='somepath') + self.assertEqual(exc.path, 'somepath') + self.assertIsNone(exc.name) + + exc = ImportError('test', path='somepath', name='somename') + self.assertEqual(exc.name, 'somename') + self.assertEqual(exc.path, 'somepath') + + + def test_main(): - run_unittest(ExceptionTests) + run_unittest(ExceptionTests, ImportErrorTests) if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #1559549: ImportError now has 'name' and 'path' attributes that are set + using keyword arguments to its constructor. They are currently not set by + import as they are meant for use by importlib. + - Issue #14474: Save and restore exception state in thread.start_new_thread() while writing error message if the thread leaves a unhandled exception. diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -605,9 +605,104 @@ /* * ImportError extends Exception */ -SimpleExtendsException(PyExc_Exception, ImportError, - "Import can't find module, or can't find name in module."); +static int +ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *msg = NULL; + PyObject *name = NULL; + PyObject *path = NULL; + +/* Macro replacement doesn't allow ## to start the first line of a macro, + so we move the assignment and NULL check into the if-statement. */ +#define GET_KWD(kwd) { \ + kwd = PyDict_GetItemString(kwds, #kwd); \ + if (kwd) { \ + Py_CLEAR(self->kwd); \ + self->kwd = kwd; \ + Py_INCREF(self->kwd);\ + if (PyDict_DelItemString(kwds, #kwd)) \ + return -1; \ + } \ + } + + if (kwds) { + GET_KWD(name); + GET_KWD(path); + } + + if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) + return -1; + if (PyTuple_GET_SIZE(args) != 1) + return 0; + if (!PyArg_UnpackTuple(args, "ImportError", 1, 1, &msg)) + return -1; + + Py_CLEAR(self->msg); /* replacing */ + self->msg = msg; + Py_INCREF(self->msg); + + return 0; +} + +static int +ImportError_clear(PyImportErrorObject *self) +{ + Py_CLEAR(self->msg); + Py_CLEAR(self->name); + Py_CLEAR(self->path); + return BaseException_clear((PyBaseExceptionObject *)self); +} + +static void +ImportError_dealloc(PyImportErrorObject *self) +{ + _PyObject_GC_UNTRACK(self); + ImportError_clear(self); + Py_TYPE(self)->tp_free((PyObject *)self); +} + +static int +ImportError_traverse(PyImportErrorObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->msg); + Py_VISIT(self->name); + Py_VISIT(self->path); + return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); +} + +static PyObject * +ImportError_str(PyImportErrorObject *self) +{ + if (self->msg) { + Py_INCREF(self->msg); + return self->msg; + } + else { + return BaseException_str((PyBaseExceptionObject *)self); + } +} + +static PyMemberDef ImportError_members[] = { + {"msg", T_OBJECT, offsetof(PyImportErrorObject, msg), 0, + PyDoc_STR("exception message")}, + {"name", T_OBJECT, offsetof(PyImportErrorObject, name), 0, + PyDoc_STR("module name")}, + {"path", T_OBJECT, offsetof(PyImportErrorObject, path), 0, + PyDoc_STR("module path")}, + {NULL} /* Sentinel */ +}; + +static PyMethodDef ImportError_methods[] = { + {NULL} +}; + +ComplexExtendsException(PyExc_Exception, ImportError, + ImportError, 0 /* new */, + ImportError_methods, ImportError_members, + 0 /* getset */, ImportError_str, + "Import can't find module, or can't find name in " + "module."); /* * OSError extends Exception diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -585,6 +585,53 @@ } #endif /* MS_WINDOWS */ +PyObject * +PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs) +{ + PyObject *val; + + /* args must at least be an empty tuple */ + if (args == NULL) + args = PyTuple_New(0); + + val = PyObject_Call(exc, args, kwargs); + if (val != NULL) { + PyErr_SetObject((PyObject *) Py_TYPE(val), val); + Py_DECREF(val); + } + + return NULL; +} + +PyObject * +PyErr_SetFromImportErrorWithNameAndPath(PyObject *msg, + PyObject *name, PyObject *path) +{ + PyObject *args = PyTuple_New(1); + PyObject *kwargs = PyDict_New(); + PyObject *result; + + if (path == NULL) + path = Py_None; + + PyTuple_SetItem(args, 0, msg); + PyDict_SetItemString(kwargs, "name", name); + PyDict_SetItemString(kwargs, "path", path); + + result = PyErr_SetExcWithArgsKwargs(PyExc_ImportError, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + return result; +} + +PyObject * +PyErr_SetFromImportErrorWithName(PyObject *msg, PyObject *name) +{ + return PyErr_SetFromImportErrorWithNameAndPath(msg, name, NULL); +} + void _PyErr_BadInternalCall(const char *filename, int lineno) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 02:32:07 2012 From: python-checkins at python.org (amaury.forgeotdarc) Date: Fri, 13 Apr 2012 02:32:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Issue14559=3A_A?= =?utf8?q?ttempt_to_fix_compilation_with_previous_versions_of_the_Microsof?= =?utf8?q?t?= Message-ID: http://hg.python.org/cpython/rev/9a6dc460ecb2 changeset: 76273:9a6dc460ecb2 branch: 2.7 parent: 76265:cc2e3c6d2669 user: Amaury Forgeot d'Arc date: Fri Apr 13 01:38:25 2012 +0200 summary: Issue14559: Attempt to fix compilation with previous versions of the Microsoft Compiler. Update the various project files with Python/random.c which was recently added. On my old Windows XP computer: - VS8.0 works reasonably. - I don't have the VS7.1 compiler. - VC6 does not compile, at least with the SDK shipped with the compiler (12 years ago!); newer SDKs might work. files: PC/VC6/pythoncore.dsp | 4 ++++ PC/VS7.1/pythoncore.vcproj | 3 +++ PC/VS8.0/pythoncore.vcproj | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/PC/VC6/pythoncore.dsp b/PC/VC6/pythoncore.dsp --- a/PC/VC6/pythoncore.dsp +++ b/PC/VC6/pythoncore.dsp @@ -663,6 +663,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Python\random.c +# End Source File +# Begin Source File + SOURCE=..\..\Objects\rangeobject.c # End Source File # Begin Source File diff --git a/PC/VS7.1/pythoncore.vcproj b/PC/VS7.1/pythoncore.vcproj --- a/PC/VS7.1/pythoncore.vcproj +++ b/PC/VS7.1/pythoncore.vcproj @@ -767,6 +767,9 @@ RelativePath="..\..\Python\pythonrun.c"> + + + + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 02:32:08 2012 From: python-checkins at python.org (amaury.forgeotdarc) Date: Fri, 13 Apr 2012 02:32:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Issue14559=3A_F?= =?utf8?q?ix_build_files_old_Microft_compilers=2E?= Message-ID: http://hg.python.org/cpython/rev/178acd78144b changeset: 76274:178acd78144b branch: 3.2 parent: 76266:427c4a63724e user: Amaury Forgeot d'Arc date: Fri Apr 13 02:14:28 2012 +0200 summary: Issue14559: Fix build files old Microft compilers. With VS8.0 at least Python compiles and works correctly. files: PC/VC6/pythoncore.dsp | 4 ++++ PC/VS7.1/pythoncore.vcproj | 3 +++ PC/VS8.0/pythoncore.vcproj | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/PC/VC6/pythoncore.dsp b/PC/VC6/pythoncore.dsp --- a/PC/VC6/pythoncore.dsp +++ b/PC/VC6/pythoncore.dsp @@ -655,6 +655,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Python\random.c +# End Source File +# Begin Source File + SOURCE=..\..\Objects\rangeobject.c # End Source File # Begin Source File diff --git a/PC/VS7.1/pythoncore.vcproj b/PC/VS7.1/pythoncore.vcproj --- a/PC/VS7.1/pythoncore.vcproj +++ b/PC/VS7.1/pythoncore.vcproj @@ -767,6 +767,9 @@ RelativePath="..\..\Python\pythonrun.c"> + + + + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 02:32:09 2012 From: python-checkins at python.org (amaury.forgeotdarc) Date: Fri, 13 Apr 2012 02:32:09 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_hg_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/e4410e69d529 changeset: 76275:e4410e69d529 parent: 76268:3df2f4a83816 parent: 76274:178acd78144b user: Amaury Forgeot d'Arc date: Fri Apr 13 02:23:59 2012 +0200 summary: hg merge 3.2 files: PC/VC6/pythoncore.dsp | 4 ++++ PC/VS7.1/pythoncore.vcproj | 3 +++ PC/VS8.0/pythoncore.vcproj | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/PC/VC6/pythoncore.dsp b/PC/VC6/pythoncore.dsp --- a/PC/VC6/pythoncore.dsp +++ b/PC/VC6/pythoncore.dsp @@ -655,6 +655,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Python\random.c +# End Source File +# Begin Source File + SOURCE=..\..\Objects\rangeobject.c # End Source File # Begin Source File diff --git a/PC/VS7.1/pythoncore.vcproj b/PC/VS7.1/pythoncore.vcproj --- a/PC/VS7.1/pythoncore.vcproj +++ b/PC/VS7.1/pythoncore.vcproj @@ -767,6 +767,9 @@ RelativePath="..\..\Python\pythonrun.c"> + + + + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 02:32:10 2012 From: python-checkins at python.org (amaury.forgeotdarc) Date: Fri, 13 Apr 2012 02:32:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_Merge_heads?= Message-ID: http://hg.python.org/cpython/rev/41989d3784d9 changeset: 76276:41989d3784d9 parent: 76275:e4410e69d529 parent: 76271:e5b30d4b0647 user: Amaury Forgeot d'Arc date: Fri Apr 13 02:24:56 2012 +0200 summary: Merge heads files: Lib/test/test_zipfile.py | 22 ++++++++++++++++++ Lib/zipfile.py | 33 ++++++++++++++++++--------- Misc/NEWS | 5 ++++ 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -970,6 +970,28 @@ with zipfile.ZipFile(TESTFN, mode="r") as zipfr: self.assertEqual(zipfr.comment, comment2) + def test_unicode_comment(self): + with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: + zipf.writestr("foo.txt", "O, for a Muse of Fire!") + with self.assertRaises(TypeError): + zipf.comment = "this is an error" + + def test_change_comment_in_empty_archive(self): + with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: + self.assertFalse(zipf.filelist) + zipf.comment = b"this is a comment" + with zipfile.ZipFile(TESTFN, "r") as zipf: + self.assertEqual(zipf.comment, b"this is a comment") + + def test_change_comment_in_nonempty_archive(self): + with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: + zipf.writestr("foo.txt", "O, for a Muse of Fire!") + with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: + self.assertTrue(zipf.filelist) + zipf.comment = b"this is a comment" + with zipfile.ZipFile(TESTFN, "r") as zipf: + self.assertEqual(zipf.comment, b"this is a comment") + def check_testzip_with_bad_crc(self, compression): """Tests that files with bad CRCs return their name from testzip.""" zipdata = self.zips_with_bad_crc[compression] diff --git a/Lib/zipfile.py b/Lib/zipfile.py --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -698,7 +698,7 @@ self.compression = compression # Method of compression self.mode = key = mode.replace('b', '')[0] self.pwd = None - self.comment = b'' + self._comment = b'' # Check if we were passed a file-like object if isinstance(file, str): @@ -774,7 +774,7 @@ print(endrec) size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory - self.comment = endrec[_ECD_COMMENT] # archive comment + self._comment = endrec[_ECD_COMMENT] # archive comment # "concat" is zero, unless zip was concatenated to another file concat = endrec[_ECD_LOCATION] - size_cd - offset_cd @@ -886,6 +886,24 @@ else: self.pwd = None + @property + def comment(self): + """The comment text associated with the ZIP file.""" + return self._comment + + @comment.setter + def comment(self, comment): + if not isinstance(comment, bytes): + raise TypeError("comment: expected bytes, got %s" % type(comment)) + # check for valid comment length + if len(comment) >= ZIP_MAX_COMMENT: + if self.debug: + print('Archive comment is too long; truncating to %d bytes' + % ZIP_MAX_COMMENT) + comment = comment[:ZIP_MAX_COMMENT] + self._comment = comment + self._didModify = True + def read(self, name, pwd=None): """Return file bytes (as a string) for name.""" with self.open(name, "r", pwd) as fp: @@ -1287,18 +1305,11 @@ centDirSize = min(centDirSize, 0xFFFFFFFF) centDirOffset = min(centDirOffset, 0xFFFFFFFF) - # check for valid comment length - if len(self.comment) >= ZIP_MAX_COMMENT: - if self.debug > 0: - msg = 'Archive comment is too long; truncating to %d bytes' \ - % ZIP_MAX_COMMENT - self.comment = self.comment[:ZIP_MAX_COMMENT] - endrec = struct.pack(structEndArchive, stringEndArchive, 0, 0, centDirCount, centDirCount, - centDirSize, centDirOffset, len(self.comment)) + centDirSize, centDirOffset, len(self._comment)) self.fp.write(endrec) - self.fp.write(self.comment) + self.fp.write(self._comment) self.fp.flush() if not self._filePassed: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,11 @@ Library ------- +- Issue #14399: zipfile now correctly adds a comment even when the zipfile + being created is otherwise empty. In addition, the TypeError that results + from trying to set a non-binary value as a comment is now now raised at the + time the comment is set rather than at the time the zipfile is written. + - trace.CoverageResults.is_ignored_filename() now ignores any name that starts with "<" and ends with ">" instead of special-casing "" and " http://hg.python.org/cpython/rev/b8e8be54e0c6 changeset: 76277:b8e8be54e0c6 branch: 3.2 parent: 76270:4186f20d9fa4 parent: 76274:178acd78144b user: Amaury Forgeot d'Arc date: Fri Apr 13 02:27:37 2012 +0200 summary: merge heads files: PC/VC6/pythoncore.dsp | 4 ++++ PC/VS7.1/pythoncore.vcproj | 3 +++ PC/VS8.0/pythoncore.vcproj | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/PC/VC6/pythoncore.dsp b/PC/VC6/pythoncore.dsp --- a/PC/VC6/pythoncore.dsp +++ b/PC/VC6/pythoncore.dsp @@ -655,6 +655,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Python\random.c +# End Source File +# Begin Source File + SOURCE=..\..\Objects\rangeobject.c # End Source File # Begin Source File diff --git a/PC/VS7.1/pythoncore.vcproj b/PC/VS7.1/pythoncore.vcproj --- a/PC/VS7.1/pythoncore.vcproj +++ b/PC/VS7.1/pythoncore.vcproj @@ -767,6 +767,9 @@ RelativePath="..\..\Python\pythonrun.c"> + + + + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 02:32:12 2012 From: python-checkins at python.org (amaury.forgeotdarc) Date: Fri, 13 Apr 2012 02:32:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/59c526e7bca5 changeset: 76278:59c526e7bca5 parent: 76272:6825fd9b00ed parent: 76276:41989d3784d9 user: Amaury Forgeot d'Arc date: Fri Apr 13 02:29:54 2012 +0200 summary: merge heads files: PC/VC6/pythoncore.dsp | 4 ++++ PC/VS7.1/pythoncore.vcproj | 3 +++ PC/VS8.0/pythoncore.vcproj | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/PC/VC6/pythoncore.dsp b/PC/VC6/pythoncore.dsp --- a/PC/VC6/pythoncore.dsp +++ b/PC/VC6/pythoncore.dsp @@ -655,6 +655,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Python\random.c +# End Source File +# Begin Source File + SOURCE=..\..\Objects\rangeobject.c # End Source File # Begin Source File diff --git a/PC/VS7.1/pythoncore.vcproj b/PC/VS7.1/pythoncore.vcproj --- a/PC/VS7.1/pythoncore.vcproj +++ b/PC/VS7.1/pythoncore.vcproj @@ -767,6 +767,9 @@ RelativePath="..\..\Python\pythonrun.c"> + + + + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 02:32:13 2012 From: python-checkins at python.org (amaury.forgeotdarc) Date: Fri, 13 Apr 2012 02:32:13 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/dd15e1cddefb changeset: 76279:dd15e1cddefb branch: 2.7 parent: 76269:ac0ec1f31b0a parent: 76273:9a6dc460ecb2 user: Amaury Forgeot d'Arc date: Fri Apr 13 02:32:51 2012 +0200 summary: merge heads files: PC/VC6/pythoncore.dsp | 4 ++++ PC/VS7.1/pythoncore.vcproj | 3 +++ PC/VS8.0/pythoncore.vcproj | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/PC/VC6/pythoncore.dsp b/PC/VC6/pythoncore.dsp --- a/PC/VC6/pythoncore.dsp +++ b/PC/VC6/pythoncore.dsp @@ -663,6 +663,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Python\random.c +# End Source File +# Begin Source File + SOURCE=..\..\Objects\rangeobject.c # End Source File # Begin Source File diff --git a/PC/VS7.1/pythoncore.vcproj b/PC/VS7.1/pythoncore.vcproj --- a/PC/VS7.1/pythoncore.vcproj +++ b/PC/VS7.1/pythoncore.vcproj @@ -767,6 +767,9 @@ RelativePath="..\..\Python\pythonrun.c"> + + + + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 03:13:16 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 13 Apr 2012 03:13:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Have_importlib_take_advanta?= =?utf8?q?ge_of_ImportError=27s_new_=27name=27_and_=27path=27?= Message-ID: http://hg.python.org/cpython/rev/c071af95772a changeset: 76280:c071af95772a parent: 76272:6825fd9b00ed user: Brett Cannon date: Thu Apr 12 21:09:01 2012 -0400 summary: Have importlib take advantage of ImportError's new 'name' and 'path' attributes. files: Lib/importlib/_bootstrap.py | 42 ++++++--- Lib/importlib/abc.py | 18 ++- Lib/importlib/test/builtin/test_loader.py | 9 +- Lib/importlib/test/extension/test_loader.py | 6 +- Lib/importlib/test/frozen/test_loader.py | 6 +- Lib/importlib/test/import_/test_caching.py | 3 +- Lib/importlib/test/import_/test_packages.py | 6 +- Lib/importlib/test/source/test_abc_loader.py | 11 +- Lib/importlib/test/source/test_file_loader.py | 16 ++- 9 files changed, 76 insertions(+), 41 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -227,7 +227,7 @@ """ def _check_name_wrapper(self, name, *args, **kwargs): if self._name != name: - raise ImportError("loader cannot handle %s" % name) + raise ImportError("loader cannot handle %s" % name, name=name) return method(self, name, *args, **kwargs) _wrap(_check_name_wrapper, method) return _check_name_wrapper @@ -237,7 +237,8 @@ """Decorator to verify the named module is built-in.""" def _requires_builtin_wrapper(self, fullname): if fullname not in sys.builtin_module_names: - raise ImportError("{0} is not a built-in module".format(fullname)) + raise ImportError("{0} is not a built-in module".format(fullname), + name=fullname) return fxn(self, fullname) _wrap(_requires_builtin_wrapper, fxn) return _requires_builtin_wrapper @@ -247,7 +248,8 @@ """Decorator to verify the named module is frozen.""" def _requires_frozen_wrapper(self, fullname): if not imp.is_frozen(fullname): - raise ImportError("{0} is not a frozen module".format(fullname)) + raise ImportError("{0} is not a frozen module".format(fullname), + name=fullname) return fxn(self, fullname) _wrap(_requires_frozen_wrapper, fxn) return _requires_frozen_wrapper @@ -372,7 +374,7 @@ filename = self.get_filename(fullname).rpartition(path_sep)[2] return filename.rsplit('.', 1)[0] == '__init__' - def _bytes_from_bytecode(self, fullname, data, source_stats): + def _bytes_from_bytecode(self, fullname, data, bytecode_path, source_stats): """Return the marshalled bytes from bytecode, verifying the magic number, timestamp and source size along the way. @@ -383,7 +385,8 @@ raw_timestamp = data[4:8] raw_size = data[8:12] if len(magic) != 4 or magic != imp.get_magic(): - raise ImportError("bad magic number in {}".format(fullname)) + raise ImportError("bad magic number in {}".format(fullname), + name=fullname, path=bytecode_path) elif len(raw_timestamp) != 4: raise EOFError("bad timestamp in {}".format(fullname)) elif len(raw_size) != 4: @@ -396,7 +399,8 @@ else: if _r_long(raw_timestamp) != source_mtime: raise ImportError( - "bytecode is stale for {}".format(fullname)) + "bytecode is stale for {}".format(fullname), + name=fullname, path=bytecode_path) try: source_size = source_stats['size'] & 0xFFFFFFFF except KeyError: @@ -404,7 +408,8 @@ else: if _r_long(raw_size) != source_size: raise ImportError( - "bytecode is stale for {}".format(fullname)) + "bytecode is stale for {}".format(fullname), + name=fullname, path=bytecode_path) # Can't return the code object as errors from marshal loading need to # propagate even when source is available. return data[12:] @@ -466,7 +471,8 @@ try: source_bytes = self.get_data(path) except IOError: - raise ImportError("source not available through get_data()") + raise ImportError("source not available through get_data()", + name=fullname) encoding = tokenize.detect_encoding(_io.BytesIO(source_bytes).readline) newline_decoder = _io.IncrementalNewlineDecoder(None, True) return newline_decoder.decode(source_bytes.decode(encoding[0])) @@ -495,6 +501,7 @@ else: try: bytes_data = self._bytes_from_bytecode(fullname, data, + bytecode_path, st) except (ImportError, EOFError): pass @@ -505,7 +512,8 @@ return found else: msg = "Non-code object in {}" - raise ImportError(msg.format(bytecode_path)) + raise ImportError(msg.format(bytecode_path), + name=fullname, path=bytecode_path) source_bytes = self.get_data(source_path) code_object = compile(source_bytes, source_path, 'exec', dont_inherit=True) @@ -604,12 +612,13 @@ def get_code(self, fullname): path = self.get_filename(fullname) data = self.get_data(path) - bytes_data = self._bytes_from_bytecode(fullname, data, None) + bytes_data = self._bytes_from_bytecode(fullname, data, path, None) found = marshal.loads(bytes_data) if isinstance(found, code_type): return found else: - raise ImportError("Non-code object in {}".format(path)) + raise ImportError("Non-code object in {}".format(path), + name=fullname, path=path) def get_source(self, fullname): """Return None as there is no source code.""" @@ -678,7 +687,8 @@ except ImportError: continue else: - raise ImportError("no path hook found for {0}".format(path)) + raise ImportError("no path hook found for {0}".format(path), + path=path) @classmethod def _path_importer_cache(cls, path, default=None): @@ -836,7 +846,7 @@ _SourceFinderDetails(), _SourcelessFinderDetails()) else: - raise ImportError("only directories are supported") + raise ImportError("only directories are supported", path=path) _DEFAULT_PATH_HOOK = _file_path_hook @@ -936,10 +946,10 @@ path = parent_module.__path__ except AttributeError: msg = (_ERR_MSG + '; {} is not a package').format(name, parent) - raise ImportError(msg) + raise ImportError(msg, name=name) loader = _find_module(name, path) if loader is None: - raise ImportError(_ERR_MSG.format(name)) + raise ImportError(_ERR_MSG.format(name), name=name) elif name not in sys.modules: # The parent import may have already imported this module. loader.load_module(name) @@ -978,7 +988,7 @@ if module is None: message = ("import of {} halted; " "None in sys.modules".format(name)) - raise ImportError(message) + raise ImportError(message, name=name) return module except KeyError: pass # Don't want to chain the exception diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -207,7 +207,7 @@ DeprecationWarning) path = self.source_path(fullname) if path is None: - raise ImportError + raise ImportError(name=fullname) else: return path @@ -235,7 +235,7 @@ if path is not None: return path raise ImportError("no source or bytecode path available for " - "{0!r}".format(fullname)) + "{0!r}".format(fullname), name=fullname) def get_code(self, fullname): """Get a code object from source or bytecode.""" @@ -253,7 +253,8 @@ magic = data[:4] if len(magic) < 4: raise ImportError( - "bad magic number in {}".format(fullname)) + "bad magic number in {}".format(fullname), + name=fullname, path=bytecode_path) raw_timestamp = data[4:8] if len(raw_timestamp) < 4: raise EOFError("bad timestamp in {}".format(fullname)) @@ -262,12 +263,14 @@ # Verify that the magic number is valid. if imp.get_magic() != magic: raise ImportError( - "bad magic number in {}".format(fullname)) + "bad magic number in {}".format(fullname), + name=fullname, path=bytecode_path) # Verify that the bytecode is not stale (only matters when # there is source to fall back on. if source_timestamp: if pyc_timestamp < source_timestamp: - raise ImportError("bytecode is stale") + raise ImportError("bytecode is stale", name=fullname, + path=bytecode_path) except (ImportError, EOFError): # If source is available give it a shot. if source_timestamp is not None: @@ -279,12 +282,13 @@ return marshal.loads(bytecode) elif source_timestamp is None: raise ImportError("no source or bytecode available to create code " - "object for {0!r}".format(fullname)) + "object for {0!r}".format(fullname), + name=fullname) # Use the source. source_path = self.source_path(fullname) if source_path is None: message = "a source path must exist to load {0}".format(fullname) - raise ImportError(message) + raise ImportError(message, name=fullname) source = self.get_data(source_path) code_object = compile(source, source_path, 'exec', dont_inherit=True) # Generate bytecode and write it out. diff --git a/Lib/importlib/test/builtin/test_loader.py b/Lib/importlib/test/builtin/test_loader.py --- a/Lib/importlib/test/builtin/test_loader.py +++ b/Lib/importlib/test/builtin/test_loader.py @@ -54,15 +54,17 @@ def test_unloadable(self): name = 'dssdsdfff' assert name not in sys.builtin_module_names - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: self.load_module(name) + self.assertEqual(cm.exception.name, name) def test_already_imported(self): # Using the name of a module already imported but not a built-in should # still fail. assert hasattr(importlib, '__file__') # Not a built-in. - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: self.load_module('importlib') + self.assertEqual(cm.exception.name, 'importlib') class InspectLoaderTests(unittest.TestCase): @@ -88,8 +90,9 @@ # Modules not built-in should raise ImportError. for meth_name in ('get_code', 'get_source', 'is_package'): method = getattr(machinery.BuiltinImporter, meth_name) - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: method(builtin_util.BAD_NAME) + self.assertRaises(builtin_util.BAD_NAME) diff --git a/Lib/importlib/test/extension/test_loader.py b/Lib/importlib/test/extension/test_loader.py --- a/Lib/importlib/test/extension/test_loader.py +++ b/Lib/importlib/test/extension/test_loader.py @@ -46,8 +46,10 @@ pass def test_unloadable(self): - with self.assertRaises(ImportError): - self.load_module('asdfjkl;') + name = 'asdfjkl;' + with self.assertRaises(ImportError) as cm: + self.load_module(name) + self.assertEqual(cm.exception.name, name) def test_main(): diff --git a/Lib/importlib/test/frozen/test_loader.py b/Lib/importlib/test/frozen/test_loader.py --- a/Lib/importlib/test/frozen/test_loader.py +++ b/Lib/importlib/test/frozen/test_loader.py @@ -57,8 +57,9 @@ def test_unloadable(self): assert machinery.FrozenImporter.find_module('_not_real') is None - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: machinery.FrozenImporter.load_module('_not_real') + self.assertEqual(cm.exception.name, '_not_real') class InspectLoaderTests(unittest.TestCase): @@ -92,8 +93,9 @@ # Raise ImportError for modules that are not frozen. for meth_name in ('get_code', 'get_source', 'is_package'): method = getattr(machinery.FrozenImporter, meth_name) - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: method('importlib') + self.assertEqual(cm.exception.name, 'importlib') def test_main(): diff --git a/Lib/importlib/test/import_/test_caching.py b/Lib/importlib/test/import_/test_caching.py --- a/Lib/importlib/test/import_/test_caching.py +++ b/Lib/importlib/test/import_/test_caching.py @@ -34,8 +34,9 @@ name = 'using_None' with util.uncache(name): sys.modules[name] = None - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: import_util.import_(name) + self.assertEqual(cm.exception.name, name) def create_mock(self, *names, return_=None): mock = util.mock_modules(*names) diff --git a/Lib/importlib/test/import_/test_packages.py b/Lib/importlib/test/import_/test_packages.py --- a/Lib/importlib/test/import_/test_packages.py +++ b/Lib/importlib/test/import_/test_packages.py @@ -19,14 +19,16 @@ def test_bad_parent(self): with util.mock_modules('pkg.module') as mock: with util.import_state(meta_path=[mock]): - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: import_util.import_('pkg.module') + self.assertEqual(cm.exception.name, 'pkg') def test_module_not_package(self): # Try to import a submodule from a non-package should raise ImportError. assert not hasattr(sys, '__path__') - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: import_util.import_('sys.no_submodules_here') + self.assertEqual(cm.exception.name, 'sys.no_submodules_here') def test_module_not_package_but_side_effects(self): # If a module injects something into sys.modules as a side-effect, then diff --git a/Lib/importlib/test/source/test_abc_loader.py b/Lib/importlib/test/source/test_abc_loader.py --- a/Lib/importlib/test/source/test_abc_loader.py +++ b/Lib/importlib/test/source/test_abc_loader.py @@ -471,8 +471,9 @@ {'path': os.path.join('path', 'to', 'mod'), 'magic': bad_magic}} mock = PyPycLoaderMock({name: None}, bc) - with util.uncache(name), self.assertRaises(ImportError): + with util.uncache(name), self.assertRaises(ImportError) as cm: mock.load_module(name) + self.assertEqual(cm.exception.name, name) def test_no_bytecode(self): # Missing code object bytecode should lead to an EOFError. @@ -516,8 +517,9 @@ # If all *_path methods return None, raise ImportError. name = 'mod' mock = PyPycLoaderMock({name: None}) - with util.uncache(name), self.assertRaises(ImportError): + with util.uncache(name), self.assertRaises(ImportError) as cm: mock.load_module(name) + self.assertEqual(cm.exception.name, name) def test_source_path_ImportError(self): # An ImportError from source_path should trigger an ImportError. @@ -533,7 +535,7 @@ mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')}) bad_meth = types.MethodType(raise_ImportError, mock) mock.bytecode_path = bad_meth - with util.uncache(name), self.assertRaises(ImportError): + with util.uncache(name), self.assertRaises(ImportError) as cm: mock.load_module(name) @@ -594,8 +596,9 @@ def raise_IOError(path): raise IOError self.loader.get_data = raise_IOError - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: self.loader.get_source(self.name) + self.assertEqual(cm.exception.name, self.name) def test_is_package(self): # Properly detect when loading a package. diff --git a/Lib/importlib/test/source/test_file_loader.py b/Lib/importlib/test/source/test_file_loader.py --- a/Lib/importlib/test/source/test_file_loader.py +++ b/Lib/importlib/test/source/test_file_loader.py @@ -232,8 +232,10 @@ lambda bc: bc[:12] + marshal.dumps(b'abcd'), del_source=del_source) file_path = mapping['_temp'] if not del_source else bytecode_path - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: self.import_(file_path, '_temp') + self.assertEqual(cm.exception.name, '_temp') + self.assertEqual(cm.exception.path, bytecode_path) def _test_bad_marshal(self, *, del_source=False): with source_util.create_modules('_temp') as mapping: @@ -381,15 +383,19 @@ def test_empty_file(self): def test(name, mapping, bytecode_path): - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: self.import_(bytecode_path, name) + self.assertEqual(cm.exception.name, name) + self.assertEqual(cm.exception.path, bytecode_path) self._test_empty_file(test, del_source=True) def test_partial_magic(self): def test(name, mapping, bytecode_path): - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: self.import_(bytecode_path, name) + self.assertEqual(cm.exception.name, name) + self.assertEqual(cm.exception.path, bytecode_path) self._test_partial_magic(test, del_source=True) def test_magic_only(self): @@ -401,8 +407,10 @@ def test_bad_magic(self): def test(name, mapping, bytecode_path): - with self.assertRaises(ImportError): + with self.assertRaises(ImportError) as cm: self.import_(bytecode_path, name) + self.assertEqual(cm.exception.name, name) + self.assertEqual(cm.exception.path, bytecode_path) self._test_bad_magic(test, del_source=True) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 03:13:17 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 13 Apr 2012 03:13:17 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_NEWS_entry_about_importlib_?= =?utf8?q?and_ImportError=27s_new_attributes=2E?= Message-ID: http://hg.python.org/cpython/rev/d06db42ae1a3 changeset: 76281:d06db42ae1a3 user: Brett Cannon date: Thu Apr 12 21:12:37 2012 -0400 summary: NEWS entry about importlib and ImportError's new attributes. 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 @@ -23,6 +23,9 @@ Library ------- +- Have importlib take advantage of ImportError's new 'name' and 'path' + attributes. + - Issue #14399: zipfile now correctly adds a comment even when the zipfile being created is otherwise empty. In addition, the TypeError that results from trying to set a non-binary value as a comment is now now raised at the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 03:13:18 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 13 Apr 2012 03:13:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_Merge?= Message-ID: http://hg.python.org/cpython/rev/edca98123f22 changeset: 76282:edca98123f22 parent: 76281:d06db42ae1a3 parent: 76278:59c526e7bca5 user: Brett Cannon date: Thu Apr 12 21:13:08 2012 -0400 summary: Merge files: PC/VC6/pythoncore.dsp | 4 ++++ PC/VS7.1/pythoncore.vcproj | 3 +++ PC/VS8.0/pythoncore.vcproj | 4 ++++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/PC/VC6/pythoncore.dsp b/PC/VC6/pythoncore.dsp --- a/PC/VC6/pythoncore.dsp +++ b/PC/VC6/pythoncore.dsp @@ -655,6 +655,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Python\random.c +# End Source File +# Begin Source File + SOURCE=..\..\Objects\rangeobject.c # End Source File # Begin Source File diff --git a/PC/VS7.1/pythoncore.vcproj b/PC/VS7.1/pythoncore.vcproj --- a/PC/VS7.1/pythoncore.vcproj +++ b/PC/VS7.1/pythoncore.vcproj @@ -767,6 +767,9 @@ RelativePath="..\..\Python\pythonrun.c"> + + + + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 03:50:42 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 13 Apr 2012 03:50:42 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_put_PyImportErrorObject_wit?= =?utf8?q?h_its_brothers?= Message-ID: http://hg.python.org/cpython/rev/be0ab722c43d changeset: 76283:be0ab722c43d user: Benjamin Peterson date: Thu Apr 12 21:50:35 2012 -0400 summary: put PyImportErrorObject with its brothers files: Include/pyerrors.h | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -28,6 +28,13 @@ typedef struct { PyException_HEAD + PyObject *msg; + PyObject *name; + PyObject *path; +} PyImportErrorObject; + +typedef struct { + PyException_HEAD PyObject *encoding; PyObject *object; Py_ssize_t start; @@ -231,13 +238,6 @@ ... ); -typedef struct { - PyException_HEAD - PyObject *msg; - PyObject *name; - PyObject *path; -} PyImportErrorObject; - #ifdef MS_WINDOWS PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename( int ierr, -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Apr 13 05:41:50 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 13 Apr 2012 05:41:50 +0200 Subject: [Python-checkins] Daily reference leaks (edca98123f22): sum=4 Message-ID: results for edca98123f22 on branch "default" -------------------------------------------- test_support leaked [0, 4, 0] references, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/refloguJMXqV', '-x'] From python-checkins at python.org Fri Apr 13 14:04:56 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 13 Apr 2012 14:04:56 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_time=2Eprocess=5Fti?= =?utf8?q?me=28=29_uses_os=2Etimes=28=29_if_available?= Message-ID: http://hg.python.org/peps/rev/68f13c2aeba7 changeset: 4240:68f13c2aeba7 user: Victor Stinner date: Fri Apr 13 14:04:37 2012 +0200 summary: PEP 418: time.process_time() uses os.times() if available files: pep-0418.txt | 52 +++++++++++++++++++++++---------------- 1 files changed, 30 insertions(+), 22 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -213,6 +213,14 @@ process_times = win32process.GetProcessTimes(handle) return (process_times['UserTime'] + process_times['KernelTime']) * 1e-7 else: + import os + try: + import resource + except ImportError: + has_resource = False + else: + has_resource = True + def process_time(): if process_time.use_process_cputime: try: @@ -220,27 +228,24 @@ except OSError: process_time.use_process_cputime = False if process_time.use_getrusage: - if process_time.getrusage is None: - try: - import resource - except ImportError: - process_time.use_getrusage = False - else: - def getrusage(): - usage = resource.getrusage(resource.RUSAGE_SELF) - return usage[0] + usage[1] - process_time.getrusage = getrusage - if process_time.use_getrusage: - try: - return process_time.getrusage() - except OSError: - process_time.use_getrusage = False + try: + usage = resource.getrusage(resource.RUSAGE_SELF) + return usage[0] + usage[1] + except OSError: + process_time.use_getrusage = False + if process_time.use_times: + try: + times = os.times() + return times[0] + times[1] + except OSError: + process_time.use_getrusage = False return _time.clock() process_time.use_process_cputime = ( hasattr(time, 'clock_gettime') and hasattr(time, 'CLOCK_PROCESS_CPUTIME_ID')) - process_time.use_getrusage = True - process_time.getrusage = None + process_time.use_getrusage = has_resource + # On OS/2, only the 5th field of os.times() is set, others are zeros + process_time.use_times = (hasattr(os, 'times') and os.name != 'os2') Existing functions @@ -1016,6 +1021,7 @@ GetProcessTimes() 100 ns No CLOCK_PROCESS_CPUTIME_ID 1 ns No getrusage() 1 ?s No +times() \- No clock() \- No (*) ========================= =============== ============= @@ -1032,16 +1038,18 @@ getrusage() Linux 3.0 4 ms clock() FreeBSD 8.2 7.8 ms clock() Linux 3.2 10 ms +times() Linux 3.0 10 ms clock() OpenBSD 5.0 10 ms GetProcessTimes() Windows Seven 15.6 ms ========================= ================ =============== The precision of clock() in this table is the result of 1 / -CLOCKS_PER_SEC. For CLOCK_PROCESS_CPUTIME_ID, the precision of this -table is the result of clock_getres(). It looks like Linux does not -implement clock_getres() and always returns 1 nanosecond. For -GetProcessTimes(), the precision is read using -GetSystemTimeAdjustment(). +CLOCKS_PER_SEC. The precision of times() in this table is the result of 1 / +HZ. HZ is a constant or read from sysconf(_SC_CLK_TCK). For +CLOCK_PROCESS_CPUTIME_ID, the precision of this table is the result of +clock_getres(). It looks like Linux does not implement clock_getres() and +always returns 1 nanosecond. For GetProcessTimes(), the precision is read +using GetSystemTimeAdjustment(). Functions -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 13 17:57:32 2012 From: python-checkins at python.org (michael.foord) Date: Fri, 13 Apr 2012 17:57:32 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_unittest=2Emock=2EPropertyM?= =?utf8?q?ock_return_value_and_attributes_are_now_standard?= Message-ID: http://hg.python.org/cpython/rev/a6236a68212e changeset: 76284:a6236a68212e user: Michael Foord date: Fri Apr 13 16:57:22 2012 +0100 summary: unittest.mock.PropertyMock return value and attributes are now standard MagicMocks files: Doc/library/unittest.mock.rst | 11 +++++++++++ Lib/unittest/mock.py | 3 +++ Lib/unittest/test/testmock/testhelpers.py | 11 +++++++++++ 3 files changed, 25 insertions(+), 0 deletions(-) diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -712,6 +712,17 @@ >>> mock_foo.mock_calls [call(), call(6)] +Because of the way mock attributes are stored you can't directly attach a +`PropertyMock` to a mock object. Instead you can attach it to the mock type +object:: + + >>> m = MagicMock() + >>> p = PropertyMock(return_value=3) + >>> type(m).foo = p + >>> m.foo + 3 + >>> p.assert_called_once_with() + Calling ~~~~~~~ diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2166,6 +2166,9 @@ Fetching a `PropertyMock` instance from an object calls the mock, with no args. Setting it calls the mock with the value being set. """ + def _get_child_mock(self, **kwargs): + return MagicMock(**kwargs) + def __get__(self, obj, obj_type): return self() def __set__(self, obj, val): diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -831,5 +831,16 @@ p.stop() + def test_propertymock_returnvalue(self): + m = MagicMock() + p = PropertyMock() + type(m).foo = p + + returned = m.foo + p.assert_called_once_with() + self.assertIsInstance(returned, MagicMock) + self.assertNotIsInstance(returned, PropertyMock) + + if __name__ == '__main__': unittest.main() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 17:59:56 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 13 Apr 2012 17:59:56 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_take_linkage_de?= =?utf8?q?f_outside_of_WITH=5FTHREAD_conditional_=28closes_=2314569=29?= Message-ID: http://hg.python.org/cpython/rev/5cc359804d61 changeset: 76285:5cc359804d61 branch: 3.2 parent: 76277:b8e8be54e0c6 user: Benjamin Peterson date: Fri Apr 13 11:58:27 2012 -0400 summary: take linkage def outside of WITH_THREAD conditional (closes #14569) files: Python/pystate.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -22,6 +22,9 @@ #endif #endif +#ifdef __cplusplus +extern "C" { +#endif #ifdef WITH_THREAD #include "pythread.h" @@ -30,10 +33,6 @@ #define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK) #define HEAD_UNLOCK() PyThread_release_lock(head_mutex) -#ifdef __cplusplus -extern "C" { -#endif - /* The single PyInterpreterState used by this process' GILState implementation */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 17:59:57 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 13 Apr 2012 17:59:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/4d1349013dd4 changeset: 76286:4d1349013dd4 parent: 76284:a6236a68212e parent: 76285:5cc359804d61 user: Benjamin Peterson date: Fri Apr 13 11:59:52 2012 -0400 summary: merge 3.2 files: Python/pystate.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -22,6 +22,9 @@ #endif #endif +#ifdef __cplusplus +extern "C" { +#endif #ifdef WITH_THREAD #include "pythread.h" @@ -30,10 +33,6 @@ #define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK) #define HEAD_UNLOCK() PyThread_release_lock(head_mutex) -#ifdef __cplusplus -extern "C" { -#endif - /* The single PyInterpreterState used by this process' GILState implementation */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 18:00:54 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 13 Apr 2012 18:00:54 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_take_linkage_de?= =?utf8?q?f_outside_of_WITH=5FTHREAD_conditional_=28closes_=2314569=29?= Message-ID: http://hg.python.org/cpython/rev/508ae5d27c2c changeset: 76287:508ae5d27c2c branch: 2.7 parent: 76279:dd15e1cddefb user: Benjamin Peterson date: Fri Apr 13 11:58:27 2012 -0400 summary: take linkage def outside of WITH_THREAD conditional (closes #14569) files: Python/pystate.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -22,6 +22,9 @@ #endif #endif +#ifdef __cplusplus +extern "C" { +#endif #ifdef WITH_THREAD #include "pythread.h" @@ -30,10 +33,6 @@ #define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK) #define HEAD_UNLOCK() PyThread_release_lock(head_mutex) -#ifdef __cplusplus -extern "C" { -#endif - /* The single PyInterpreterState used by this process' GILState implementation */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 18:39:34 2012 From: python-checkins at python.org (michael.foord) Date: Fri, 13 Apr 2012 18:39:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Make_unittest=2Emock=2Ecrea?= =?utf8?q?te=5Fautospec_resilient_against_AttributeError_on_original?= Message-ID: http://hg.python.org/cpython/rev/1f841cb8e056 changeset: 76288:1f841cb8e056 parent: 76286:4d1349013dd4 user: Michael Foord date: Fri Apr 13 17:39:16 2012 +0100 summary: Make unittest.mock.create_autospec resilient against AttributeError on original object files: Lib/unittest/mock.py | 8 ++- Lib/unittest/test/testmock/testhelpers.py | 23 +++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2044,10 +2044,14 @@ # object to mock it so we would rather trigger a property than mock # the property descriptor. Likewise we want to mock out dynamically # provided attributes. - # XXXX what about attributes that raise exceptions on being fetched + # XXXX what about attributes that raise exceptions other than + # AttributeError on being fetched? # we could be resilient against it, or catch and propagate the # exception when the attribute is fetched from the mock - original = getattr(spec, entry) + try: + original = getattr(spec, entry) + except AttributeError: + continue kwargs = {'spec': original} if spec_set: diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -651,6 +651,29 @@ mock.f.assert_called_with(3, 4) + def test_skip_attributeerrors(self): + class Raiser(object): + def __get__(self, obj, type=None): + if obj is None: + raise AttributeError('Can only be accessed via an instance') + + class RaiserClass(object): + raiser = Raiser() + + @staticmethod + def existing(a, b): + return a + b + + s = create_autospec(RaiserClass) + self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3)) + s.existing(1, 2) + self.assertRaises(AttributeError, lambda: s.nonexisting) + + # check we can fetch the raiser attribute and it has no spec + obj = s.raiser + obj.foo, obj.bar + + def test_signature_class(self): class Foo(object): def __init__(self, a, b=3): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 21:51:36 2012 From: python-checkins at python.org (michael.foord) Date: Fri, 13 Apr 2012 21:51:36 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Minor_docstring_/_docs_corr?= =?utf8?q?ections_for_unittest=2Emock?= Message-ID: http://hg.python.org/cpython/rev/9db3bedcd86c changeset: 76289:9db3bedcd86c user: Michael Foord date: Fri Apr 13 20:51:20 2012 +0100 summary: Minor docstring / docs corrections for unittest.mock files: Doc/library/unittest.mock-examples.rst | 2 +- Doc/library/unittest.mock.rst | 8 ++++---- Lib/unittest/mock.py | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -99,7 +99,7 @@ In the example below we have a function `some_function` that instantiates `Foo` and calls a method on it. The call to `patch` replaces the class `Foo` with a mock. The `Foo` instance is the result of calling the mock, so it is configured -by modify the mock :attr:`~Mock.return_value`. +by modifying the mock :attr:`~Mock.return_value`. >>> def some_function(): ... instance = module.Foo() diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -236,10 +236,10 @@ * `wraps`: Item for the mock object to wrap. If `wraps` is not None then calling the Mock will pass the call through to the wrapped object - (returning the real result and ignoring `return_value`). Attribute access - on the mock will return a Mock object that wraps the corresponding - attribute of the wrapped object (so attempting to access an attribute - that doesn't exist will raise an `AttributeError`). + (returning the real result). Attribute access on the mock will return a + Mock object that wraps the corresponding attribute of the wrapped + object (so attempting to access an attribute that doesn't exist will + raise an `AttributeError`). If the mock has an explicit `return_value` set then calls are not passed to the wrapped object and the `return_value` is returned instead. diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -941,12 +941,12 @@ this is a new Mock (created on first access). See the `return_value` attribute. - * `wraps`: Item for the mock object to wrap. If `wraps` is not None - then calling the Mock will pass the call through to the wrapped object - (returning the real result and ignoring `return_value`). Attribute - access on the mock will return a Mock object that wraps the corresponding - attribute of the wrapped object (so attempting to access an attribute that - doesn't exist will raise an `AttributeError`). + * `wraps`: Item for the mock object to wrap. If `wraps` is not None then + calling the Mock will pass the call through to the wrapped object + (returning the real result). Attribute access on the mock will return a + Mock object that wraps the corresponding attribute of the wrapped object + (so attempting to access an attribute that doesn't exist will raise an + `AttributeError`). If the mock has an explicit `return_value` set then calls are not passed to the wrapped object and the `return_value` is returned instead. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 13 22:47:49 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 13 Apr 2012 22:47:49 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_precision_in_Py?= =?utf8?q?thon=3B_clock=28=29_will_not_be_removed=3B_add_users?= Message-ID: http://hg.python.org/peps/rev/87ed37a05fad changeset: 4241:87ed37a05fad user: Victor Stinner date: Fri Apr 13 22:07:36 2012 +0200 summary: PEP 418: Add precision in Python; clock() will not be removed; add users files: pep-0418.txt | 103 +++++++++++++---------- pep-0418/clock_precision.py | 55 ++++++++++++ 2 files changed, 111 insertions(+), 47 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -58,9 +58,20 @@ period * ``time.process_time()``: profiling, CPU time of the process -``time.clock()`` is deprecated by this PEP because it is not portable: -``time.perf_counter()`` or ``time.process_time()`` should be used -instead, depending on your requirements. +Users of new functions: + + * time.monotonic(): concurrent.futures, multiprocessing, queue, subprocess, + telnet and threading modules to implement timeout + * time.perf_counter(): trace and timeit modules, pybench program + * time.process_time(): profile module + * time.get_clock_info(): pybench program to display information about the + timer like the precision or the resolution + +The ``time.clock()`` function is deprecated by this PEP because it is not +portable: it behaves differently depending on the operating system. +``time.perf_counter()`` or ``time.process_time()`` should be used instead, +depending on your requirements. ``time.clock()`` is marked as deprecated but +is not planned for removal. Python functions @@ -84,7 +95,7 @@ * Mandatory keys: - * "function" (str): name of the underlying operating system + * "implementation" (str): name of the underlying operating system function. Examples: "QueryPerformanceCounter()", "clock_gettime(CLOCK_REALTIME)". * "resolution" (float): resolution in seconds of the clock @@ -105,7 +116,7 @@ undefined, so that only the difference between the results of consecutive calls is valid. -Availability: Windows, Mac OS X, Unix. +Availability: Windows, Mac OS X, Unix, Solaris. Not available on GNU/Hurd. Pseudo-code [#pseudo]_:: @@ -710,18 +721,18 @@ Examples of clock precision on x86_64: -========================= ================ =============== -Name Operating system Precision -========================= ================ =============== -CLOCK_MONOTONIC_RAW Linux 3.2 1 ns -CLOCK_MONOTONIC Linux 3.2 1 ns -CLOCK_HIGHRES SunOS 5.11 2 ns -CLOCK_MONOTONIC SunOS 5.11 2 ns -QueryPerformanceCounter Windows Seven 10 ns -CLOCK_MONOTONIC FreeBSD 8.2 11 ns -CLOCK_MONOTONIC OpenBSD 5.0 10 ms -GetTickCount Windows Seven 15.6 ms -========================= ================ =============== +========================= ================ ========= =================== +Name Operating system Precision Precision in Python +========================= ================ ========= =================== +CLOCK_MONOTONIC_RAW Linux 3.2 1 ns 3.0 ?s +CLOCK_MONOTONIC Linux 3.2 1 ns 1.6 ?s +CLOCK_HIGHRES SunOS 5.11 2 ns ? +CLOCK_MONOTONIC SunOS 5.11 2 ns ? +QueryPerformanceCounter Windows Seven 10 ns ? +CLOCK_MONOTONIC FreeBSD 8.2 11 ns ? +CLOCK_MONOTONIC OpenBSD 5.0 10 ms ? +GetTickCount Windows Seven 15.6 ms ? +========================= ================ ========= =================== For CLOCK_xxx clocks, the precision of this table is the result of ``clock_getres()``. It looks like Linux does not implement ``clock_getres()`` @@ -886,8 +897,6 @@ WaitForSingleObject() uses the same timer as GetTickCount() with the same precision. -GetTickCount() has an precision of 55 ms on Windows 9x. - Windows: timeGetTime ^^^^^^^^^^^^^^^^^^^^ @@ -962,15 +971,15 @@ Examples of clock precision on x86_64: -========================= ================ =============== -Name Operating system Precision -========================= ================ =============== -CLOCK_REALTIME Linux 3.2 1 ns -CLOCK_REALTIME FreeBSD 8.2 11 ns -CLOCK_REALTIME SunOS 5.11 10 ms -CLOCK_REALTIME OpenBSD 5.0 10 ms -GetSystemTimeAsFileTime Windows Seven 15.6 ms -========================= ================ =============== +========================= ================ ========= =================== +Name Operating system Precision Precision in Python +========================= ================ ========= =================== +CLOCK_REALTIME Linux 3.2 1 ns 1.9 ?s +CLOCK_REALTIME FreeBSD 8.2 11 ns ? +CLOCK_REALTIME SunOS 5.11 10 ms ? +CLOCK_REALTIME OpenBSD 5.0 10 ms ? +GetSystemTimeAsFileTime Windows Seven 15.6 ms ? +========================= ================ ========= =================== For CLOCK_REALTIME, the precision of this table is the result of clock_getres(). It looks like Linux does not implement clock_getres() @@ -1030,18 +1039,18 @@ Examples of clock precision on x86_64: -========================= ================ =============== -Name Operating system Precision -========================= ================ =============== -CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns -clock() SunOS 5.11 1 ?s -getrusage() Linux 3.0 4 ms -clock() FreeBSD 8.2 7.8 ms -clock() Linux 3.2 10 ms -times() Linux 3.0 10 ms -clock() OpenBSD 5.0 10 ms -GetProcessTimes() Windows Seven 15.6 ms -========================= ================ =============== +========================= ================ ========= =================== +Name Operating system Precision Precision in Python +========================= ================ ========= =================== +CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns 3.3 ?s +clock() SunOS 5.11 1 ?s ? +getrusage() Linux 3.0 4 ms 4 ms +clock() FreeBSD 8.2 7.8 ms ? +clock() Linux 3.2 1 ?s 10 ms +times() Linux 3.0 10 ms 10 ms +clock() OpenBSD 5.0 10 ms ? +GetProcessTimes() Windows Seven 15.6 ms ? +========================= ================ ========= =================== The precision of clock() in this table is the result of 1 / CLOCKS_PER_SEC. The precision of times() in this table is the result of 1 / @@ -1090,13 +1099,13 @@ Examples of clock precision on x86_64: -========================= ================ =============== -Name Operating system Precision -========================= ================ =============== -CLOCK_THREAD_CPUTIME_ID Linux 3.2 1 ns -CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s -GetThreadTimes() Windows Seven 15.6 ms -========================= ================ =============== +========================= ================ =============== =================== +Name Operating system Precision Precision in Python +========================= ================ =============== =================== +CLOCK_THREAD_CPUTIME_ID Linux 3.2 1 ns ? +CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s ? +GetThreadTimes() Windows Seven 15.6 ms ? +========================= ================ =============== =================== For CLOCK_THREAD_CPUTIME_ID, the precision of this table is the result of clock_getres(). It looks like Linux does not implement diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_precision.py new file mode 100644 --- /dev/null +++ b/pep-0418/clock_precision.py @@ -0,0 +1,55 @@ +import time + +def compute_precision(func): + previous = func() + precision = None + points = 0 + min_points = 100 + while points < min_points: + value = func() + if value == previous: + continue + dt = value - previous + previous = value + if precision is not None: + precision = min(precision, dt) + else: + precision = dt + if precision < 10e-6: + min_points = 5000 + elif precision < 1e-3: + min_points = 1000 + points += 1 + return dt + +def format_duration(dt): + if dt >= 1e-3: + return "%.1f ms" % (dt * 1e3) + if dt >= 1e-6: + return "%.1f ?s" % (dt * 1e6) + else: + return "%.1f ns" % (dt * 1e9) + +def test_clock(name, func): + precision = compute_precision(func) + print("%s:" % name) + print("- precision in Python: %s" % format_duration(precision)) + + +for name in ('clock', 'perf_counter', 'process_time', 'monotonic', 'time'): + func = getattr(time, name) + test_clock("%s()" % name, func) + info = time.get_clock_info(name) + if 'precision' in info: + print("- announced precision: %s" % format_duration(info['precision'])) + print("- function: %s" % info['function']) + print("- resolution: %s" % format_duration(info['resolution'])) + +clock_ids = [name for name in dir(time) if name.startswith("CLOCK_")] +for clock_id_text in clock_ids: + clock_id = getattr(time, clock_id_text) + name = 'clock_gettime(%s)' % clock_id_text + def gettime(): + return time.clock_gettime(clock_id) + test_clock(name, gettime) + -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 13 23:25:15 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 13 Apr 2012 23:25:15 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_precision_in_Py?= =?utf8?q?thon_of_FreeBSD_clocks?= Message-ID: http://hg.python.org/peps/rev/a8fc654a42c0 changeset: 4242:a8fc654a42c0 user: Victor Stinner date: Fri Apr 13 23:24:44 2012 +0200 summary: PEP 418: Add precision in Python of FreeBSD clocks files: pep-0418.txt | 33 +++++++++++++----------- pep-0418/clock_precision.py | 8 +++--- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -678,8 +678,8 @@ * "slewing": change the clock frequency to be slightly faster or slower (which is done with ``adjtime()``). Since the slew rate is - limited to 0.5 ms/s, each second of adjustment requires an - amortization interval of 2000 s. Thus, an adjustment of many + limited to 0.5 millisecond per second, each second of adjustment requires an + amortization interval of 2000 seconds. Thus, an adjustment of many seconds can take hours or days to amortize. * "stepping": jump by a large amount in a single discrete step (which is done with ``settimeofday()``) @@ -713,6 +713,7 @@ CLOCK_MONOTONIC 1 ns Slewed on Linux Yes No CLOCK_MONOTONIC_RAW 1 ns No Yes No CLOCK_BOOTTIME 1 ns ? Yes Yes +CLOCK_UPTIME 1 ns No Yes ? mach_absolute_time() 1 ns No Yes No QueryPerformanceCounter() \- No Yes ? GetTickCount[64]() 1 ms No Yes Yes @@ -724,14 +725,15 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== -CLOCK_MONOTONIC_RAW Linux 3.2 1 ns 3.0 ?s -CLOCK_MONOTONIC Linux 3.2 1 ns 1.6 ?s +CLOCK_MONOTONIC_RAW Linux 3.2 1 ns 3 ?s +CLOCK_MONOTONIC Linux 3.2 1 ns 2 ?s CLOCK_HIGHRES SunOS 5.11 2 ns ? CLOCK_MONOTONIC SunOS 5.11 2 ns ? QueryPerformanceCounter Windows Seven 10 ns ? -CLOCK_MONOTONIC FreeBSD 8.2 11 ns ? +CLOCK_UPTIME FreeBSD 8.2 11 ns 9 ?s +CLOCK_MONOTONIC FreeBSD 8.2 11 ns 7 ?s CLOCK_MONOTONIC OpenBSD 5.0 10 ms ? -GetTickCount Windows Seven 15.6 ms ? +GetTickCount Windows Seven 16 ms ? ========================= ================ ========= =================== For CLOCK_xxx clocks, the precision of this table is the result of @@ -974,11 +976,11 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== -CLOCK_REALTIME Linux 3.2 1 ns 1.9 ?s -CLOCK_REALTIME FreeBSD 8.2 11 ns ? +CLOCK_REALTIME Linux 3.2 1 ns 2 ?s +CLOCK_REALTIME FreeBSD 8.2 11 ns 7 ?s CLOCK_REALTIME SunOS 5.11 10 ms ? CLOCK_REALTIME OpenBSD 5.0 10 ms ? -GetSystemTimeAsFileTime Windows Seven 15.6 ms ? +GetSystemTimeAsFileTime Windows Seven 16 ms ? ========================= ================ ========= =================== For CLOCK_REALTIME, the precision of this table is the result of @@ -1042,14 +1044,15 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== -CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns 3.3 ?s +CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns 3 ?s clock() SunOS 5.11 1 ?s ? getrusage() Linux 3.0 4 ms 4 ms -clock() FreeBSD 8.2 7.8 ms ? +getrusage() FreeBSD 8.2 - 1 ?s +clock() FreeBSD 8.2 8 ms 8 ms clock() Linux 3.2 1 ?s 10 ms times() Linux 3.0 10 ms 10 ms clock() OpenBSD 5.0 10 ms ? -GetProcessTimes() Windows Seven 15.6 ms ? +GetProcessTimes() Windows Seven 16 ms ? ========================= ================ ========= =================== The precision of clock() in this table is the result of 1 / @@ -1102,9 +1105,9 @@ ========================= ================ =============== =================== Name Operating system Precision Precision in Python ========================= ================ =============== =================== -CLOCK_THREAD_CPUTIME_ID Linux 3.2 1 ns ? -CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s ? -GetThreadTimes() Windows Seven 15.6 ms ? +CLOCK_THREAD_CPUTIME_ID Linux 3.2 1 ns 6 ?s +CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s 1 ?s +GetThreadTimes() Windows Seven 16 ms ? ========================= ================ =============== =================== For CLOCK_THREAD_CPUTIME_ID, the precision of this table is the result diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_precision.py --- a/pep-0418/clock_precision.py +++ b/pep-0418/clock_precision.py @@ -24,11 +24,11 @@ def format_duration(dt): if dt >= 1e-3: - return "%.1f ms" % (dt * 1e3) + return "%.0f ms" % (dt * 1e3) if dt >= 1e-6: - return "%.1f ?s" % (dt * 1e6) + return "%.0f ?s" % (dt * 1e6) else: - return "%.1f ns" % (dt * 1e9) + return "%.0f ns" % (dt * 1e9) def test_clock(name, func): precision = compute_precision(func) @@ -42,7 +42,7 @@ info = time.get_clock_info(name) if 'precision' in info: print("- announced precision: %s" % format_duration(info['precision'])) - print("- function: %s" % info['function']) + print("- implementation: %s" % info['implementation']) print("- resolution: %s" % format_duration(info['resolution'])) clock_ids = [name for name in dir(time) if name.startswith("CLOCK_")] -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 13 23:44:37 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 13 Apr 2012 23:44:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_clock=5Fgettime/getres/?= =?utf8?q?settime=3A_PyArg=5FParseTuple=28=29_expects_an_int?= Message-ID: http://hg.python.org/cpython/rev/06c4792143ab changeset: 76290:06c4792143ab user: Victor Stinner date: Fri Apr 13 23:44:05 2012 +0200 summary: Fix clock_gettime/getres/settime: PyArg_ParseTuple() expects an int Only use a single #ifdef for the 3 functions. files: Modules/timemodule.c | 14 ++++---------- 1 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -139,7 +139,7 @@ time_clock_gettime(PyObject *self, PyObject *args) { int ret; - clockid_t clk_id; + int clk_id; struct timespec tp; if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) @@ -162,7 +162,7 @@ static PyObject * time_clock_settime(PyObject *self, PyObject *args) { - clockid_t clk_id; + int clk_id; PyObject *obj; struct timespec tp; int ret; @@ -185,14 +185,12 @@ "clock_settime(clk_id, time)\n\ \n\ Set the time of the specified clock clk_id."); -#endif -#ifdef HAVE_CLOCK_GETRES static PyObject * time_clock_getres(PyObject *self, PyObject *args) { int ret; - clockid_t clk_id; + int clk_id; struct timespec tp; if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id)) @@ -211,7 +209,7 @@ "clock_getres(clk_id) -> floating point number\n\ \n\ Return the resolution (precision) of the specified clock clk_id."); -#endif +#endif /* HAVE_CLOCK_GETTIME */ static PyObject * time_sleep(PyObject *self, PyObject *args) @@ -1009,11 +1007,7 @@ #endif #ifdef HAVE_CLOCK_GETTIME {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, -#endif -#ifdef HAVE_CLOCK_GETTIME {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, -#endif -#ifdef HAVE_CLOCK_GETRES {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, #endif {"sleep", time_sleep, METH_VARARGS, sleep_doc}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 00:07:03 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 14 Apr 2012 00:07:03 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_move_outside_WI?= =?utf8?q?TH=5FTHREAD_conditional?= Message-ID: http://hg.python.org/cpython/rev/49f52d14b65c changeset: 76291:49f52d14b65c branch: 3.2 parent: 76285:5cc359804d61 user: Benjamin Peterson date: Fri Apr 13 18:06:36 2012 -0400 summary: move outside WITH_THREAD conditional files: Python/pystate.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -726,10 +726,10 @@ PyEval_SaveThread(); } +#endif /* WITH_THREAD */ + #ifdef __cplusplus } #endif -#endif /* WITH_THREAD */ - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 00:07:04 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 14 Apr 2012 00:07:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/6d239e55e65a changeset: 76292:6d239e55e65a parent: 76290:06c4792143ab parent: 76291:49f52d14b65c user: Benjamin Peterson date: Fri Apr 13 18:06:42 2012 -0400 summary: merge 3.2 files: Python/pystate.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -726,10 +726,10 @@ PyEval_SaveThread(); } +#endif /* WITH_THREAD */ + #ifdef __cplusplus } #endif -#endif /* WITH_THREAD */ - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 00:07:04 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 14 Apr 2012 00:07:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_move_outside_WI?= =?utf8?q?TH=5FTHREAD_conditional?= Message-ID: http://hg.python.org/cpython/rev/ab157c169f6e changeset: 76293:ab157c169f6e branch: 2.7 parent: 76287:508ae5d27c2c user: Benjamin Peterson date: Fri Apr 13 18:06:36 2012 -0400 summary: move outside WITH_THREAD conditional files: Python/pystate.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -653,10 +653,10 @@ PyEval_SaveThread(); } +#endif /* WITH_THREAD */ + #ifdef __cplusplus } #endif -#endif /* WITH_THREAD */ - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 00:18:24 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 14 Apr 2012 00:18:24 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Complete_=22Precisi?= =?utf8?q?on_in_Python=22_column_in_the_different_tables?= Message-ID: http://hg.python.org/peps/rev/d454bba39db5 changeset: 4243:d454bba39db5 user: Victor Stinner date: Sat Apr 14 00:17:54 2012 +0200 summary: PEP 418: Complete "Precision in Python" column in the different tables files: pep-0418.txt | 67 ++++++++++++++++++++------------------- 1 files changed, 35 insertions(+), 32 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -725,15 +725,15 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== +CLOCK_HIGHRES SunOS 5.11 2 ns 2 ?s +CLOCK_MONOTONIC Linux 3.2 1 ns 2 ?s +CLOCK_MONOTONIC SunOS 5.11 2 ns 3 ?s CLOCK_MONOTONIC_RAW Linux 3.2 1 ns 3 ?s -CLOCK_MONOTONIC Linux 3.2 1 ns 2 ?s -CLOCK_HIGHRES SunOS 5.11 2 ns ? -CLOCK_MONOTONIC SunOS 5.11 2 ns ? -QueryPerformanceCounter Windows Seven 10 ns ? +CLOCK_MONOTONIC FreeBSD 8.2 11 ns 7 ?s +CLOCK_MONOTONIC OpenBSD 5.0 10 ms 7 ?s +QueryPerformanceCounter Windows Seven 10 ns 9 ?s CLOCK_UPTIME FreeBSD 8.2 11 ns 9 ?s -CLOCK_MONOTONIC FreeBSD 8.2 11 ns 7 ?s -CLOCK_MONOTONIC OpenBSD 5.0 10 ms ? -GetTickCount Windows Seven 16 ms ? +GetTickCount Windows Seven 16 ms 15 ms ========================= ================ ========= =================== For CLOCK_xxx clocks, the precision of this table is the result of @@ -976,11 +976,11 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== +CLOCK_REALTIME SunOS 5.11 10 ms 2 ?s CLOCK_REALTIME Linux 3.2 1 ns 2 ?s CLOCK_REALTIME FreeBSD 8.2 11 ns 7 ?s -CLOCK_REALTIME SunOS 5.11 10 ms ? -CLOCK_REALTIME OpenBSD 5.0 10 ms ? -GetSystemTimeAsFileTime Windows Seven 16 ms ? +CLOCK_REALTIME OpenBSD 5.0 10 ms 10 ?s +GetSystemTimeAsFileTime Windows Seven 16 ms 1 ms ========================= ================ ========= =================== For CLOCK_REALTIME, the precision of this table is the result of @@ -1026,15 +1026,15 @@ The process time cannot be set. It is not monotonic: the clocks stop while the process is idle. -========================= =============== ============= -Name Resolution Include sleep -========================= =============== ============= -GetProcessTimes() 100 ns No -CLOCK_PROCESS_CPUTIME_ID 1 ns No -getrusage() 1 ?s No -times() \- No -clock() \- No (*) -========================= =============== ============= +========================= ========== ============= +Name Resolution Include sleep +========================= ========== ============= +GetProcessTimes() 100 ns No +CLOCK_PROCESS_CPUTIME_ID 1 ns No +getrusage(RUSAGE_SELF) 1 ?s No +times() \- No +clock() \- No (*) +========================= ========== ============= (*) On Windows, clock() does include time elapsed during a sleep. It does not on other operating systems. @@ -1044,15 +1044,18 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== +getrusage(RUSAGE_SELF) FreeBSD 8.2 \- 1 ?s CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns 3 ?s -clock() SunOS 5.11 1 ?s ? -getrusage() Linux 3.0 4 ms 4 ms -getrusage() FreeBSD 8.2 - 1 ?s +getrusage(RUSAGE_SELF) SunOS 5.11 \- 3 ?s +getrusage(RUSAGE_SELF) Linux 3.0 4 ms 4 ms +getrusage(RUSAGE_SELF) OpenBSD 5.0 \- 8 ms clock() FreeBSD 8.2 8 ms 8 ms clock() Linux 3.2 1 ?s 10 ms times() Linux 3.0 10 ms 10 ms -clock() OpenBSD 5.0 10 ms ? -GetProcessTimes() Windows Seven 16 ms ? +clock() OpenBSD 5.0 10 ms 10 ms +times() OpenBSD 5.0 10 ms 10 ms +GetProcessTimes() Windows Seven 16 ms 16 ms +clock() SunOS 5.11 1 ?s 10 ms ========================= ================ ========= =================== The precision of clock() in this table is the result of 1 / @@ -1080,7 +1083,7 @@ program. * times() -* getrusage(): ru_utime and ru_stime fields +* getrusage(RUSAGE_SELF): ru_utime and ru_stime fields Python source code includes a portable library to get the process time (CPU time): `Tools/pybench/systimes.py @@ -1093,21 +1096,21 @@ The thread time cannot be set. It is not monotonic: the clocks stop while the thread is idle. -========================= =============== +========================= ========== Name Resolution -========================= =============== -GetThreadTimes() 100 ns -CLOCK_THREAD_CPUTIME_ID 1 ns -========================= =============== +========================= ========== +CLOCK_THREAD_CPUTIME_ID 1 ns +GetThreadTimes() 100 ns +========================= ========== Examples of clock precision on x86_64: ========================= ================ =============== =================== Name Operating system Precision Precision in Python ========================= ================ =============== =================== +CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s 1 ?s CLOCK_THREAD_CPUTIME_ID Linux 3.2 1 ns 6 ?s -CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s 1 ?s -GetThreadTimes() Windows Seven 16 ms ? +GetThreadTimes() Windows Seven 16 ms 16 ms ========================= ================ =============== =================== For CLOCK_THREAD_CPUTIME_ID, the precision of this table is the result -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 14 00:47:32 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 14 Apr 2012 00:47:32 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Cleanup_info_on_pre?= =?utf8?q?cision?= Message-ID: http://hg.python.org/peps/rev/47ffc9008585 changeset: 4244:47ffc9008585 user: Victor Stinner date: Sat Apr 14 00:47:00 2012 +0200 summary: PEP 418: Cleanup info on precision files: pep-0418.txt | 69 ++++++++++-------------- pep-0418/clock_precision.py | 2 + 2 files changed, 30 insertions(+), 41 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -708,9 +708,10 @@ ========================= ========== =============== ============= =============== Name Resolution Adjusted Include sleep Include suspend ========================= ========== =============== ============= =============== -gethrtime 1 ns No Yes Yes +gethrtime() 1 ns No Yes Yes CLOCK_HIGHRES 1 ns No Yes ? CLOCK_MONOTONIC 1 ns Slewed on Linux Yes No +CLOCK_MONOTONIC_COARSE 1 ns Slewed on Linux Yes No CLOCK_MONOTONIC_RAW 1 ns No Yes No CLOCK_BOOTTIME 1 ns ? Yes Yes CLOCK_UPTIME 1 ns No Yes ? @@ -733,13 +734,10 @@ CLOCK_MONOTONIC OpenBSD 5.0 10 ms 7 ?s QueryPerformanceCounter Windows Seven 10 ns 9 ?s CLOCK_UPTIME FreeBSD 8.2 11 ns 9 ?s +CLOCK_MONOTONIC_COARSE Linux 3.3 1 ms 1 ms GetTickCount Windows Seven 16 ms 15 ms ========================= ================ ========= =================== -For CLOCK_xxx clocks, the precision of this table is the result of -``clock_getres()``. It looks like Linux does not implement ``clock_getres()`` -and always returns 1 nanosecond. - mach_absolute_time ^^^^^^^^^^^^^^^^^^ @@ -761,7 +759,8 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW represent monotonic time since -some unspecified starting point. They cannot be set. +some unspecified starting point. They cannot be set. The precision +can be read using ``clock_getres()``. Documentation: refer to the manual page of your operating system. Examples: @@ -800,6 +799,9 @@ CLOCK_MONOTONIC stops while the machine is suspended. +Linux provides also CLOCK_MONOTONIC_COARSE since Linux 2.6.32. It is +similar to CLOCK_MONOTONIC, less precise but faster. + ``clock_gettime()`` fails if the system does not support the specified clock, even if the standard C library supports it. For example, CLOCK_MONOTONIC_RAW requires a kernel version 2.6.28 or later. @@ -809,16 +811,12 @@ ``clock_gettime()`` requires to link the program against the rt (real-time) library. -.. note:: - - Linux provides also CLOCK_MONOTONIC_COARSE since Linux 2.6.32 which - has less accuracy than CLOCK_MONOTONIC but is faster. - Windows: QueryPerformanceCounter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ High-resolution performance counter. It is monotonic. -QueryPerformanceFrequency() gives its frequency. +The frequency of the counter can be read using QueryPerformanceFrequency(). +The precision is 1 / QueryPerformanceFrequency(). It has a much higher resolution, but has lower long term precision than GetTickCount() and timeGetTime() clocks. For example, it will @@ -884,6 +882,7 @@ `_, `GetTickCount64() `_. +The precision can be read using GetSystemTimeAdjustment(). The elapsed time retrieved by GetTickCount() or GetTickCount64() includes time the system spends in sleep or hibernation. @@ -939,6 +938,8 @@ created with a clockid_t value of CLOCK_HIGHRES, the system will attempt to use an optimal hardware source. +The precision of CLOCK_HIGHRES can be read using ``clock_getres()``. + Solaris: gethrtime ^^^^^^^^^^^^^^^^^^ @@ -965,6 +966,7 @@ Name Resolution Include sleep ========================= =============== ============= CLOCK_REALTIME 1 ns Yes +CLOCK_REALTIME_COARSE 1 ns Yes GetSystemTimeAsFileTime 100 ns Yes gettimeofday() 1 ?s Yes ftime() 1 ms Yes @@ -980,18 +982,10 @@ CLOCK_REALTIME Linux 3.2 1 ns 2 ?s CLOCK_REALTIME FreeBSD 8.2 11 ns 7 ?s CLOCK_REALTIME OpenBSD 5.0 10 ms 10 ?s +CLOCK_REALTIME_COARSE Linux 3.3 1 ms 1 ms GetSystemTimeAsFileTime Windows Seven 16 ms 1 ms ========================= ================ ========= =================== -For CLOCK_REALTIME, the precision of this table is the result of -clock_getres(). It looks like Linux does not implement clock_getres() -and always returns 1 nanosecond. - -.. note:: - - Linux provides also CLOCK_REALTIME_COARSE since Linux 2.6.32 which - has less accurate than CLOCK_REALTIME but is faster. - Windows: GetSystemTimeAsFileTime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1008,12 +1002,16 @@ System time on UNIX ^^^^^^^^^^^^^^^^^^^ -gettimeofday(), ftime(), time() and clock_gettime(CLOCK_REALTIME) -return the system clock. +gettimeofday(), ftime(), time() and clock_gettime(CLOCK_REALTIME) return +the system clock. The precision of CLOCK_REALTIME can be read using +clock_getres(). The system time can be set using settimeofday() or clock_settime(CLOCK_REALTIME). +Linux provides also CLOCK_REALTIME_COARSE since Linux 2.6.32. It is similar +to CLOCK_REALTIME, less precise but faster. + Alexander Shishkin proposed an API for Linux to be notified when the system clock is changed: `timerfd: add TFD_NOTIFY_CLOCK_SET to watch for clock changes `_ (4th version of the API, March 2011). The @@ -1058,23 +1056,14 @@ clock() SunOS 5.11 1 ?s 10 ms ========================= ================ ========= =================== -The precision of clock() in this table is the result of 1 / -CLOCKS_PER_SEC. The precision of times() in this table is the result of 1 / -HZ. HZ is a constant or read from sysconf(_SC_CLK_TCK). For -CLOCK_PROCESS_CPUTIME_ID, the precision of this table is the result of -clock_getres(). It looks like Linux does not implement clock_getres() and -always returns 1 nanosecond. For GetProcessTimes(), the precision is read -using GetSystemTimeAdjustment(). - - Functions ^^^^^^^^^ * Windows: GetProcessTimes(). The precision can be read using GetSystemTimeAdjustment(). * clock_gettime(CLOCK_PROCESS_CPUTIME_ID): High-resolution per-process - timer from the CPU. -* clock(): + timer from the CPU. The precision can be read using clock_getres(). +* clock(). The precision is 1 / CLOCKS_PER_SEC. * Windows: The elapsed wall-clock time since the start of the process (elapsed time in seconds times CLOCKS_PER_SEC). It can @@ -1082,8 +1071,10 @@ * UNIX: returns an approximation of processor time used by the program. -* times() -* getrusage(RUSAGE_SELF): ru_utime and ru_stime fields +* getrusage(RUSAGE_SELF) returns a structure of resource usage of the currenet + process. ru_utime is use CPU time and ru_stime is the system CPU time. +* times(): structure of process times. The precision is 1 / ticks_per_seconds, + where ticks_per_seconds is sysconf(_SC_CLK_TCK) or the HZ constant. Python source code includes a portable library to get the process time (CPU time): `Tools/pybench/systimes.py @@ -1113,10 +1104,6 @@ GetThreadTimes() Windows Seven 16 ms 16 ms ========================= ================ =============== =================== -For CLOCK_THREAD_CPUTIME_ID, the precision of this table is the result -of clock_getres(). It looks like Linux does not implement -clock_getres() and always return 1 nanosecond. For GetThreadTimes(), -the precision is read using GetSystemTimeAdjustment(). Functions ^^^^^^^^^ @@ -1124,7 +1111,7 @@ * Windows: GetThreadTimes(). The precision can be read using GetSystemTimeAdjustment(). * clock_gettime(CLOCK_THREAD_CPUTIME_ID): Thread-specific CPU-time - clock. + clock. The precision can be read using of clock_getres(). See also pthread_getcpuclockid(). diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_precision.py --- a/pep-0418/clock_precision.py +++ b/pep-0418/clock_precision.py @@ -52,4 +52,6 @@ def gettime(): return time.clock_gettime(clock_id) test_clock(name, gettime) + precision = time.clock_getres(clock_id) + print("- announced precision: %s" % format_duration(precision)) -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 14 01:15:06 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 14 Apr 2012 01:15:06 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_CLOCK=5FBOOTTIM?= =?utf8?q?E_precision_in_Python?= Message-ID: http://hg.python.org/peps/rev/816fff771b51 changeset: 4245:816fff771b51 user: Victor Stinner date: Sat Apr 14 01:14:34 2012 +0200 summary: PEP 418: Add CLOCK_BOOTTIME precision in Python files: pep-0418.txt | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -730,6 +730,7 @@ CLOCK_MONOTONIC Linux 3.2 1 ns 2 ?s CLOCK_MONOTONIC SunOS 5.11 2 ns 3 ?s CLOCK_MONOTONIC_RAW Linux 3.2 1 ns 3 ?s +CLOCK_BOOTTIME Linux 3.3 1 ns 3 ?s CLOCK_MONOTONIC FreeBSD 8.2 11 ns 7 ?s CLOCK_MONOTONIC OpenBSD 5.0 10 ms 7 ?s QueryPerformanceCounter Windows Seven 10 ns 9 ?s @@ -1045,7 +1046,7 @@ getrusage(RUSAGE_SELF) FreeBSD 8.2 \- 1 ?s CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns 3 ?s getrusage(RUSAGE_SELF) SunOS 5.11 \- 3 ?s -getrusage(RUSAGE_SELF) Linux 3.0 4 ms 4 ms +getrusage(RUSAGE_SELF) Linux 3.3 \- 1 ms getrusage(RUSAGE_SELF) OpenBSD 5.0 \- 8 ms clock() FreeBSD 8.2 8 ms 8 ms clock() Linux 3.2 1 ?s 10 ms -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 14 01:45:56 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 14 Apr 2012 01:45:56 +0200 (CEST) Subject: [Python-checkins] r88947 - tracker/roundup-src/roundup/backends/indexer_xapian.py Message-ID: <3VTwbm07fnzMlD@mail.python.org> Author: r.david.murray Date: Sat Apr 14 01:45:55 2012 New Revision: 88947 Log: xapian search was only returning the first 10 hits. Return them all. And the hits returned included file content matches, which get filtered out, so most of our searches were getting pretty anemic result lists. Modified: tracker/roundup-src/roundup/backends/indexer_xapian.py Modified: tracker/roundup-src/roundup/backends/indexer_xapian.py ============================================================================== --- tracker/roundup-src/roundup/backends/indexer_xapian.py (original) +++ tracker/roundup-src/roundup/backends/indexer_xapian.py Sat Apr 14 01:45:55 2012 @@ -108,7 +108,7 @@ query = xapian.Query(xapian.Query.OP_AND, terms) enquire.set_query(query) - matches = enquire.get_mset(0, 10) + matches = enquire.get_mset(0, database.get_doccount()) return [tuple(m.document.get_data().split(':')) for m in matches] From python-checkins at python.org Sat Apr 14 02:09:01 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 14 Apr 2012 02:09:01 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fill_=22Include_sus?= =?utf8?q?pend=22_column_of_all_tables?= Message-ID: http://hg.python.org/peps/rev/4836feae4d4c changeset: 4246:4836feae4d4c user: Victor Stinner date: Sat Apr 14 02:08:16 2012 +0200 summary: PEP 418: Fill "Include suspend" column of all tables files: pep-0418.txt | 90 +++++++++++++++++++++------------------ 1 files changed, 49 insertions(+), 41 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -160,14 +160,11 @@ has a better precision than ``GetTickCount()``. It is not reliable and has too many issues. -.. note:: - - ``time.monotonic()`` detects ``GetTickCount()`` integer overflow - (32 bits, roll-over after 49.7 days): it increases a delta by 2\ - :sup:`32` each time than an overflow is detected. The delta is - stored in the process-local state and so the value of - ``time.monotonic()`` may be different in two Python processes - running for more than 49 days. +``time.monotonic()`` detects ``GetTickCount()`` integer overflow (32 bits, +roll-over after 49.7 days): it increases a delta by 2\ :sup:`32` each time +than an overflow is detected. The delta is stored in the process-local +state and so the value of ``time.monotonic()`` may be different in two +Python processes running for more than 49 days. time.perf_counter() @@ -391,7 +388,8 @@ :Accuracy: Is the answer correct? Any clock will eventually ; if a clock is intended to match , it will need to be - back to the "true" time. + back to the "true" time. See also `Accuracy and precision + `_. :Adjusted: Resetting a clock to the correct time. This may be done either @@ -709,7 +707,7 @@ Name Resolution Adjusted Include sleep Include suspend ========================= ========== =============== ============= =============== gethrtime() 1 ns No Yes Yes -CLOCK_HIGHRES 1 ns No Yes ? +CLOCK_HIGHRES 1 ns No Yes Yes CLOCK_MONOTONIC 1 ns Slewed on Linux Yes No CLOCK_MONOTONIC_COARSE 1 ns Slewed on Linux Yes No CLOCK_MONOTONIC_RAW 1 ns No Yes No @@ -807,10 +805,6 @@ clock, even if the standard C library supports it. For example, CLOCK_MONOTONIC_RAW requires a kernel version 2.6.28 or later. -.. note:: - - ``clock_gettime()`` requires to link the program against the rt - (real-time) library. Windows: QueryPerformanceCounter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -963,16 +957,16 @@ System time clocks ------------------ -========================= =============== ============= -Name Resolution Include sleep -========================= =============== ============= -CLOCK_REALTIME 1 ns Yes -CLOCK_REALTIME_COARSE 1 ns Yes -GetSystemTimeAsFileTime 100 ns Yes -gettimeofday() 1 ?s Yes -ftime() 1 ms Yes -time() 1 sec Yes -========================= =============== ============= +========================= =============== ============= =============== +Name Resolution Include sleep Include suspend +========================= =============== ============= =============== +CLOCK_REALTIME 1 ns Yes Yes +CLOCK_REALTIME_COARSE 1 ns Yes Yes +GetSystemTimeAsFileTime 100 ns Yes Yes +gettimeofday() 1 ?s Yes Yes +ftime() 1 ms Yes Yes +time() 1 sec Yes Yes +========================= =============== ============= =============== Examples of clock precision on x86_64: @@ -1025,15 +1019,15 @@ The process time cannot be set. It is not monotonic: the clocks stop while the process is idle. -========================= ========== ============= -Name Resolution Include sleep -========================= ========== ============= -GetProcessTimes() 100 ns No -CLOCK_PROCESS_CPUTIME_ID 1 ns No -getrusage(RUSAGE_SELF) 1 ?s No -times() \- No -clock() \- No (*) -========================= ========== ============= +========================= ========== ============= =============== +Name Resolution Include sleep Include suspend +========================= ========== ============= =============== +GetProcessTimes() 100 ns No No +CLOCK_PROCESS_CPUTIME_ID 1 ns No No +getrusage(RUSAGE_SELF) 1 ?s No No +times() \- No No +clock() \- No (*) No +========================= ========== ============= =============== (*) On Windows, clock() does include time elapsed during a sleep. It does not on other operating systems. @@ -1081,6 +1075,10 @@ time): `Tools/pybench/systimes.py `_. +See also the `QueryProcessCycleTime() function +`_ +(sum of the cycle time of all threads). + Thread time ----------- @@ -1088,12 +1086,12 @@ The thread time cannot be set. It is not monotonic: the clocks stop while the thread is idle. -========================= ========== -Name Resolution -========================= ========== -CLOCK_THREAD_CPUTIME_ID 1 ns -GetThreadTimes() 100 ns -========================= ========== +========================= ========== ============= =============== +Name Resolution Include sleep Include suspend +========================= ========== ============= =============== +CLOCK_THREAD_CPUTIME_ID 1 ns Yes Epoch changes +GetThreadTimes() 100 ns No ? +========================= ========== ============= =============== Examples of clock precision on x86_64: @@ -1105,16 +1103,22 @@ GetThreadTimes() Windows Seven 16 ms 16 ms ========================= ================ =============== =================== +CLOCK_THREAD_CPUTIME_ID returns a number of CPU cycles, not a number of +seconds. + Functions ^^^^^^^^^ * Windows: GetThreadTimes(). The precision can be read using - GetSystemTimeAdjustment(). + GetSystemTimeAdjustment(). `MSDN documentation of GetThreadTimes() + `_. * clock_gettime(CLOCK_THREAD_CPUTIME_ID): Thread-specific CPU-time clock. The precision can be read using of clock_getres(). -See also pthread_getcpuclockid(). +See also the `QueryThreadCycleTime() function +`_ +(cycle time for the specified thread) and pthread_getcpuclockid(). Windows: QueryUnbiasedInterruptTime @@ -1130,6 +1134,10 @@ QueryUnbiasedInterruptTime() was introduced in Windows 7. +See also `QueryIdleProcessorCycleTime() function +`_ +(cycle time for the idle thread of each processor) + Sleep, suspend and monotonic time ================================= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 14 02:23:19 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 14 Apr 2012 02:23:19 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Rephrase_sleep/susp?= =?utf8?q?end_paragraphs?= Message-ID: http://hg.python.org/peps/rev/ca1aefe4d618 changeset: 4247:ca1aefe4d618 user: Victor Stinner date: Sat Apr 14 02:22:50 2012 +0200 summary: PEP 418: Rephrase sleep/suspend paragraphs files: pep-0418.txt | 65 +++++++++++++++++---------------------- 1 files changed, 28 insertions(+), 37 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -697,8 +697,8 @@ `_. -Operating system clocks -======================= +Operating system time functions +=============================== Monotonic clocks ---------------- @@ -1139,43 +1139,14 @@ (cycle time for the idle thread of each processor) -Sleep, suspend and monotonic time -================================= - -Linux +Sleep ----- -sleep() is not affected by system clock update. - -On Linux, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW includes time the -system spends in sleep; but it does not include time spent in -hibernation (ACPI S3 mode). If the system clock jumps backward, -CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW are not affected. - -Other operating systems ------------------------ - -On Windows, GetTickCount() and GetTickCount64() include time the system spends -in sleep; sleep() is not affected by system clock update. The WM_POWERBROADCAST -message is send to Windows application to notify them of power-management -events (ex: ower status has changed). - -On FreeBSD 8, CLOCK_MONOTONIC include time the system spends in sleep; -sleep() is not affected by system clock update. - -On OpenIndiana, CLOCK_MONOTONIC include time the system spends in -sleep; sleep() is not affected by system clock update. - -On Mac OS X, mach_absolute_time() include time the system spends in -sleep; sleep() is not affected by system clock update. Sleep is -interrupted during suspend. Read also: `Registering and unregistering for sleep -and wake notifications -`_ (Technical -Q&A QA1340). - - -Sleeping -======== +Suspend execution of the process for the given number of seconds. Sleep is not +affected by system clock update. Sleep is paused during system suspend. For +example, if a process sleeps for 60 seconds and the system is suspended for 30 +seconds in the middle of the sleep, the sleep duration is 90 seconds in the +real time. Sleep can be interrupted by a signal: the function fails with EINTR. @@ -1204,8 +1175,8 @@ ======================== ========== -Classic functions ------------------ +Functions +^^^^^^^^^ * sleep(seconds) * usleep(microseconds) @@ -1216,7 +1187,7 @@ clock_nanosleep ---------------- +^^^^^^^^^^^^^^^ clock_nanosleep(clock_id, flags, nanoseconds, remaining): `Linux manpage of clock_nanosleep() @@ -1233,7 +1204,7 @@ select() --------- +^^^^^^^^ select(nfds, readfds, writefds, exceptfs, timeout). @@ -1247,7 +1218,7 @@ Other functions ---------------- +^^^^^^^^^^^^^^^ * poll(), epoll() * sigtimedwait(). POSIX: "If the Monotonic Clock option is supported, @@ -1264,6 +1235,21 @@ the same precision. +System Standby +============== + +The ACPI power state "S3" is as system standby mode, also called "Suspend to +RAM". RAM remains powered. + +On Windows, the WM_POWERBROADCAST message is send to Windows application +to notify them of power-management events (ex: ower status has changed). + +For Mac OS X, read `Registering and unregistering for sleep +and wake notifications +`_ (Technical +Q&A QA1340). + + Alternatives: API design ======================== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 14 02:27:05 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 14 Apr 2012 02:27:05 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Reorganize_sections?= =?utf8?q?=2C_move_Alternatives_after_Python_functions?= Message-ID: http://hg.python.org/peps/rev/218690427516 changeset: 4248:218690427516 user: Victor Stinner date: Sat Apr 14 02:26:35 2012 +0200 summary: PEP 418: Reorganize sections, move Alternatives after Python functions files: pep-0418.txt | 246 +++++++++++++++++++------------------- 1 files changed, 126 insertions(+), 120 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -382,6 +382,132 @@ +Alternatives: API design +======================== + +Other names for new functions +----------------------------- + +time.monotonic(): + +* time.counter() +* time.seconds() +* time.steady() +* time.timeout_clock() +* time.wallclock(): it is not the system time aka the "wall clock", + but a monotonic clock with an unspecified starting point + +The name "time.try_monotonic()" was also proposed when +time.monotonic() was falling back to the system clock when no +monotonic clock was available. + +time.perf_counter(): + + * time.hires() + * time.highres() + * time.timer() + + +Only expose operating system clocks +----------------------------------- + +To not have to define high-level clocks, which is a difficult task, a +simpler approach is to only expose operating system clocks. +time.clock_gettime() and related clock identifiers were already added +to Python 3.3 for example. + + +Fallback to system clock +------------------------ + +If no monotonic clock is available, time.monotonic() falls back to the +system clock. + +Issues: + +* It is hard to define correctly such function in the documentation: + is it monotonic? is it steady? is it adjusted? +* Some user want to decide what to do when no monotonic clock is + available: use another clock, display an error, or do something + else? + + +One function choosing the clock from a list of constraints +---------------------------------------------------------- + +``time.get_clock(*flags)`` with the following flags: + +* time.MONOTONIC: clock cannot go backward +* time.STEADY: clock rate is steady and the clock is not adjusted +* time.HIGHRES: clock with the highest precision + +time.get_clock() returns None if the clock is found and so calls can +be chained using the or operator. Example:: + + get_time = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time() + t = get_time() + +Example of flags of system clocks: + +* QueryPerformanceCounter: MONOTONIC | HIGHRES +* GetTickCount: MONOTONIC | STEADY +* CLOCK_MONOTONIC: MONOTONIC | STEADY (or only MONOTONIC on Linux) +* CLOCK_MONOTONIC_RAW: MONOTONIC | STEADY +* gettimeofday(): (no flag) + + +One function with a flag: time.monotonic(fallback=True) +------------------------------------------------------- + +* time.monotonic(fallback=True) falls back to the system clock if no + monotonic clock is available or if the monotonic clock failed. +* time.monotonic(fallback=False) raises OSError if monotonic clock + fails and NotImplementedError if the system does not provide a + monotonic clock + +"A keyword argument that gets passed as a constant in the caller is +usually poor API." + +Raising NotImplementedError for a function is something uncommon in +Python and should be avoided. + + +One function, no flag +--------------------- + +time.monotonic() returns (time: float, is_monotonic: bool). + +An alternative is to use a function attribute: +time.monotonic.is_monotonic. The attribute value would be None before +the first call to time.monotonic(). + + +Working around operating system bugs? +------------------------------------- + +Should Python ensure manually that a monotonic clock is truly +monotonic by computing the maximum with the clock value and the +previous value? + +Since it's relatively straightforward to cache the last value returned +using a static variable, it might be interesting to use this to make +sure that the values returned are indeed monotonic. + +* Virtual machines provide less reliable clocks. +* QueryPerformanceCounter() has known bugs (only one is not fixed yet) + +Python may only work around a specific known operating system bug: +`KB274323`_ contains a code example to workaround the bug (use +GetTickCount() to detect QueryPerformanceCounter() leap). + +Issues of a hacked monotonic function: + +* if the clock is accidentally set forward by an hour and then back + again, you wouldn't have a useful clock for an hour +* the cache is not shared between processes so different processes + wouldn't see the same clock value + + Glossary ======== @@ -1250,132 +1376,6 @@ Q&A QA1340). -Alternatives: API design -======================== - -Other names for new functions ------------------------------ - -time.monotonic(): - -* time.counter() -* time.seconds() -* time.steady() -* time.timeout_clock() -* time.wallclock(): it is not the system time aka the "wall clock", - but a monotonic clock with an unspecified starting point - -The name "time.try_monotonic()" was also proposed when -time.monotonic() was falling back to the system clock when no -monotonic clock was available. - -time.perf_counter(): - - * time.hires() - * time.highres() - * time.timer() - - -Only expose operating system clocks ------------------------------------ - -To not have to define high-level clocks, which is a difficult task, a -simpler approach is to only expose operating system clocks. -time.clock_gettime() and related clock identifiers were already added -to Python 3.3 for example. - - -Fallback to system clock ------------------------- - -If no monotonic clock is available, time.monotonic() falls back to the -system clock. - -Issues: - -* It is hard to define correctly such function in the documentation: - is it monotonic? is it steady? is it adjusted? -* Some user want to decide what to do when no monotonic clock is - available: use another clock, display an error, or do something - else? - - -One function choosing the clock from a list of constraints ----------------------------------------------------------- - -``time.get_clock(*flags)`` with the following flags: - -* time.MONOTONIC: clock cannot go backward -* time.STEADY: clock rate is steady and the clock is not adjusted -* time.HIGHRES: clock with the highest precision - -time.get_clock() returns None if the clock is found and so calls can -be chained using the or operator. Example:: - - get_time = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time() - t = get_time() - -Example of flags of system clocks: - -* QueryPerformanceCounter: MONOTONIC | HIGHRES -* GetTickCount: MONOTONIC | STEADY -* CLOCK_MONOTONIC: MONOTONIC | STEADY (or only MONOTONIC on Linux) -* CLOCK_MONOTONIC_RAW: MONOTONIC | STEADY -* gettimeofday(): (no flag) - - -One function with a flag: time.monotonic(fallback=True) -------------------------------------------------------- - -* time.monotonic(fallback=True) falls back to the system clock if no - monotonic clock is available or if the monotonic clock failed. -* time.monotonic(fallback=False) raises OSError if monotonic clock - fails and NotImplementedError if the system does not provide a - monotonic clock - -"A keyword argument that gets passed as a constant in the caller is -usually poor API." - -Raising NotImplementedError for a function is something uncommon in -Python and should be avoided. - - -One function, no flag ---------------------- - -time.monotonic() returns (time: float, is_monotonic: bool). - -An alternative is to use a function attribute: -time.monotonic.is_monotonic. The attribute value would be None before -the first call to time.monotonic(). - - -Working around operating system bugs? -===================================== - -Should Python ensure manually that a monotonic clock is truly -monotonic by computing the maximum with the clock value and the -previous value? - -Since it's relatively straightforward to cache the last value returned -using a static variable, it might be interesting to use this to make -sure that the values returned are indeed monotonic. - -* Virtual machines provide less reliable clocks. -* QueryPerformanceCounter() has known bugs (only one is not fixed yet) - -Python may only work around a specific known operating system bug: -`KB274323`_ contains a code example to workaround the bug (use -GetTickCount() to detect QueryPerformanceCounter() leap). - -Issues of a hacked monotonic function: - -* if the clock is accidentally set forward by an hour and then back - again, you wouldn't have a useful clock for an hour -* the cache is not shared between processes so different processes - wouldn't see the same clock value - - Footnotes ========= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 14 02:46:18 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 14 Apr 2012 02:46:18 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Cleanup_the_Process?= =?utf8?q?_Time_table?= Message-ID: http://hg.python.org/peps/rev/45fdf1653f8c changeset: 4249:45fdf1653f8c user: Victor Stinner date: Sat Apr 14 02:45:49 2012 +0200 summary: PEP 418: Cleanup the Process Time table files: pep-0418.txt | 37 ++++++++++++++++++------------------- 1 files changed, 18 insertions(+), 19 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -77,7 +77,7 @@ Python functions ================ -New functions +New Functions ------------- time.get_clock_info(name) @@ -256,7 +256,7 @@ process_time.use_times = (hasattr(os, 'times') and os.name != 'os2') -Existing functions +Existing Functions ------------------ time.time() @@ -340,8 +340,8 @@ seconds = int(seconds) _time.sleep(seconds) -Deprecated functions --------------------- +Deprecated Function +------------------- time.clock() ^^^^^^^^^^^^ @@ -826,7 +826,7 @@ Operating system time functions =============================== -Monotonic clocks +Monotonic Clocks ---------------- ========================= ========== =============== ============= =============== @@ -1080,8 +1080,8 @@ On Solaris, gethrtime() is the same as clock_gettime(CLOCK_MONOTONIC). -System time clocks ------------------- +System clocks +------------- ========================= =============== ============= =============== Name Resolution Include sleep Include suspend @@ -1139,24 +1139,21 @@ API is not accepted yet, CLOCK_BOOTTIME provides a similar feature. -Process time +Process Time ------------ The process time cannot be set. It is not monotonic: the clocks stop while the process is idle. -========================= ========== ============= =============== -Name Resolution Include sleep Include suspend -========================= ========== ============= =============== -GetProcessTimes() 100 ns No No -CLOCK_PROCESS_CPUTIME_ID 1 ns No No -getrusage(RUSAGE_SELF) 1 ?s No No -times() \- No No -clock() \- No (*) No -========================= ========== ============= =============== - -(*) On Windows, clock() does include time elapsed during a sleep. It does not -on other operating systems. +========================= ========== ============================ =============== +Name Resolution Include sleep Include suspend +========================= ========== ============================ =============== +GetProcessTimes() 100 ns No No +CLOCK_PROCESS_CPUTIME_ID 1 ns No No +getrusage(RUSAGE_SELF) 1 ?s No No +times() \- No No +clock() \- Yes on Windows, No otherwise No +========================= ========== ============================ =============== Examples of clock precision on x86_64: @@ -1206,7 +1203,7 @@ (sum of the cycle time of all threads). -Thread time +Thread Time ----------- The thread time cannot be set. It is not monotonic: the clocks stop -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 14 03:27:45 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 14 Apr 2012 03:27:45 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0Mzk5OiBjb3Jy?= =?utf8?q?ected_news_item?= Message-ID: http://hg.python.org/cpython/rev/b3b7f9dd7ce4 changeset: 76294:b3b7f9dd7ce4 branch: 3.2 parent: 76291:49f52d14b65c user: R David Murray date: Fri Apr 13 21:24:27 2012 -0400 summary: #14399: corrected news item files: Misc/NEWS | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,10 +39,10 @@ Library ------- -- Issue #14399: zipfile now correctly adds a comment even when the zipfile - being created is otherwise empty. In addition, the TypeError that results - from trying to set a non-binary value as a comment is now now raised at the - time the comment is set rather than at the time the zipfile is written. +- Issue #14399: zipfile now recognizes that the archive has been modified even + if only the comment is changed. In addition, the TypeError that results from + trying to set a non-binary value as a comment is now now raised at the time + the comment is set rather than at the time the zipfile is written. - Issue #7978: socketserver now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 03:27:46 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 14 Apr 2012 03:27:46 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0Mzk5OiBjb3Jy?= =?utf8?q?ected_news_item?= Message-ID: http://hg.python.org/cpython/rev/225126c9d4b5 changeset: 76295:225126c9d4b5 branch: 2.7 parent: 76293:ab157c169f6e user: R David Murray date: Fri Apr 13 21:27:00 2012 -0400 summary: #14399: corrected news item files: Misc/NEWS | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -44,9 +44,9 @@ Library ------- -- Issue #14399: zipfile now correctly adds a comment even when the zipfile - being created is otherwise empty. As a consequence of this fix, ZipFile is - now a new style class. +- Issue #14399: zipfile now recognizes that the archive has been modified even + if only the comment is changed. As a consequence of this fix, ZipFile is now + a new style class. - Issue #7978: SocketServer now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 03:27:47 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 14 Apr 2012 03:27:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_=2314399=3A_corrected_news_item?= Message-ID: http://hg.python.org/cpython/rev/160245735299 changeset: 76296:160245735299 parent: 76292:6d239e55e65a parent: 76294:b3b7f9dd7ce4 user: R David Murray date: Fri Apr 13 21:27:19 2012 -0400 summary: Merge #14399: corrected news item files: Misc/NEWS | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,10 +26,10 @@ - Have importlib take advantage of ImportError's new 'name' and 'path' attributes. -- Issue #14399: zipfile now correctly adds a comment even when the zipfile - being created is otherwise empty. In addition, the TypeError that results - from trying to set a non-binary value as a comment is now now raised at the - time the comment is set rather than at the time the zipfile is written. +- Issue #14399: zipfile now recognizes that the archive has been modified even + if only the comment is changed. In addition, the TypeError that results from + trying to set a non-binary value as a comment is now now raised at the time + the comment is set rather than at the time the zipfile is written. - trace.CoverageResults.is_ignored_filename() now ignores any name that starts with "<" and ends with ">" instead of special-casing "" and -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 04:52:42 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 14 Apr 2012 04:52:42 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NTM1OiBmaXgg?= =?utf8?q?code_highlight_in_multiprocessing_examples=2E__Patch_by_Tshepang?= Message-ID: http://hg.python.org/cpython/rev/635966f6d3de changeset: 76297:635966f6d3de branch: 3.2 parent: 76294:b3b7f9dd7ce4 user: Ezio Melotti date: Fri Apr 13 20:50:48 2012 -0600 summary: #14535: fix code highlight in multiprocessing examples. Patch by Tshepang Lekhonkhobe. files: Doc/library/multiprocessing.rst | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1114,7 +1114,7 @@ HELLO WORLD [(3.515625, 39.0625), (33.0625, 4.0), (5.640625, 90.25)] -.. highlight:: python +.. highlight:: python3 .. _multiprocessing-managers: @@ -2256,16 +2256,19 @@ Demonstration of how to create and use customized managers and proxies: .. literalinclude:: ../includes/mp_newtype.py + :language: python3 Using :class:`Pool`: .. literalinclude:: ../includes/mp_pool.py + :language: python3 Synchronization types like locks, conditions and queues: .. literalinclude:: ../includes/mp_synchronize.py + :language: python3 An example showing how to use queues to feed tasks to a collection of worker -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 04:52:42 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 14 Apr 2012 04:52:42 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314535=3A_merge_with_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/957e2c71beef changeset: 76298:957e2c71beef parent: 76296:160245735299 parent: 76297:635966f6d3de user: Ezio Melotti date: Fri Apr 13 20:52:29 2012 -0600 summary: #14535: merge with 3.2. files: Doc/library/multiprocessing.rst | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1142,7 +1142,7 @@ HELLO WORLD [(3.515625, 39.0625), (33.0625, 4.0), (5.640625, 90.25)] -.. highlight:: python +.. highlight:: python3 .. _multiprocessing-managers: @@ -2370,16 +2370,19 @@ Demonstration of how to create and use customized managers and proxies: .. literalinclude:: ../includes/mp_newtype.py + :language: python3 Using :class:`Pool`: .. literalinclude:: ../includes/mp_pool.py + :language: python3 Synchronization types like locks, conditions and queues: .. literalinclude:: ../includes/mp_synchronize.py + :language: python3 An example showing how to use queues to feed tasks to a collection of worker -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 05:05:47 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 14 Apr 2012 05:05:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Fix_highlight_a?= =?utf8?q?nd_spacing_in_json_example=2E?= Message-ID: http://hg.python.org/cpython/rev/5fe73997523a changeset: 76299:5fe73997523a branch: 3.2 parent: 76297:635966f6d3de user: Ezio Melotti date: Fri Apr 13 21:02:18 2012 -0600 summary: Fix highlight and spacing in json example. files: Doc/library/json.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/json.rst b/Doc/library/json.rst --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -90,7 +90,7 @@ ['[2.0', ', 1.0', ']'] -.. highlight:: none +.. highlight:: bash Using json.tool from the shell to validate and pretty-print:: @@ -98,10 +98,10 @@ { "json": "obj" } - $ echo '{ 1.2:3.4}' | python -mjson.tool - Expecting property name: line 1 column 2 (char 2) + $ echo '{1.2:3.4}' | python -mjson.tool + Expecting property name: line 1 column 1 (char 1) -.. highlight:: python +.. highlight:: python3 .. note:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 05:05:48 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 14 Apr 2012 05:05:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_highlight_and_spacing_fixes_in_json_example_with_3=2E2?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/60f7719c0415 changeset: 76300:60f7719c0415 parent: 76298:957e2c71beef parent: 76299:5fe73997523a user: Ezio Melotti date: Fri Apr 13 21:05:36 2012 -0600 summary: Merge highlight and spacing fixes in json example with 3.2. files: Doc/library/json.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/json.rst b/Doc/library/json.rst --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -90,7 +90,7 @@ ['[2.0', ', 1.0', ']'] -.. highlight:: none +.. highlight:: bash Using json.tool from the shell to validate and pretty-print:: @@ -98,10 +98,10 @@ { "json": "obj" } - $ echo '{ 1.2:3.4}' | python -mjson.tool - Expecting property name: line 1 column 2 (char 2) + $ echo '{1.2:3.4}' | python -mjson.tool + Expecting property name: line 1 column 1 (char 1) -.. highlight:: python +.. highlight:: python3 .. note:: -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Apr 14 05:36:15 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 14 Apr 2012 05:36:15 +0200 Subject: [Python-checkins] Daily reference leaks (160245735299): sum=0 Message-ID: results for 160245735299 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogxN4Rk7', '-x'] From python-checkins at python.org Sat Apr 14 16:02:28 2012 From: python-checkins at python.org (sandro.tosi) Date: Sat, 14 Apr 2012 16:02:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_fix_typo=3B_tha?= =?utf8?q?nks_to_J=C3=A9r=C3=B4me_Mainka_from_docs=40?= Message-ID: http://hg.python.org/cpython/rev/38f8c779f5f8 changeset: 76301:38f8c779f5f8 branch: 3.2 parent: 76299:5fe73997523a user: Sandro Tosi date: Sat Apr 14 16:01:17 2012 +0200 summary: fix typo; thanks to J?r?me Mainka from docs@ files: Doc/library/random.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/random.rst b/Doc/library/random.rst --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -309,7 +309,7 @@ >>> random.sample([1, 2, 3, 4, 5], 3) # Three samples without replacement [4, 1, 5] -A common task is to make a :func:`random.choice` with weighted probababilites. +A common task is to make a :func:`random.choice` with weighted probabilities. If the weights are small integer ratios, a simple technique is to build a sample population with repeats:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 16:02:29 2012 From: python-checkins at python.org (sandro.tosi) Date: Sat, 14 Apr 2012 16:02:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/e730da0cd489 changeset: 76302:e730da0cd489 parent: 76300:60f7719c0415 parent: 76301:38f8c779f5f8 user: Sandro Tosi date: Sat Apr 14 16:01:49 2012 +0200 summary: merge with 3.2 files: Doc/library/random.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/random.rst b/Doc/library/random.rst --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -315,7 +315,7 @@ >>> random.sample([1, 2, 3, 4, 5], 3) # Three samples without replacement [4, 1, 5] -A common task is to make a :func:`random.choice` with weighted probababilites. +A common task is to make a :func:`random.choice` with weighted probabilities. If the weights are small integer ratios, a simple technique is to build a sample population with repeats:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 20:11:10 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2012 20:11:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=232377=3A_Make_impor?= =?utf8?q?tlib_the_implementation_of_=5F=5Fimport=5F=5F=28=29=2E?= Message-ID: http://hg.python.org/cpython/rev/2dd046be2c88 changeset: 76303:2dd046be2c88 user: Brett Cannon date: Sat Apr 14 14:10:13 2012 -0400 summary: Issue #2377: Make importlib the implementation of __import__(). importlib._bootstrap is now frozen into Python/importlib.h and stored as _frozen_importlib in sys.modules. Py_Initialize() loads the frozen code along with sys and imp and then uses _frozen_importlib._install() to set builtins.__import__() w/ _frozen_importlib.__import__(). files: Include/abstract.h | 4 + Include/dictobject.h | 2 + Include/import.h | 3 + Include/pystate.h | 2 + Include/pythonrun.h | 2 +- Lib/importlib/_bootstrap.py | 35 +- Lib/importlib/test/import_/test_path.py | 2 +- Lib/importlib/test/import_/util.py | 1 - Lib/importlib/test/regrtest.py | 12 - Lib/importlib/test/source/test_file_loader.py | 2 +- Lib/importlib/test/source/test_finder.py | 9 +- Lib/importlib/test/source/test_path_hook.py | 3 +- Lib/importlib/test/source/test_source_encoding.py | 4 +- Lib/importlib/test/util.py | 2 +- Lib/os.py | 2 + Lib/pydoc.py | 5 +- Lib/site.py | 3 +- Lib/test/test_frozen.py | 26 +- Lib/test/test_import.py | 7 +- Lib/test/test_pkg.py | 31 +- Lib/test/test_pydoc.py | 9 +- Lib/test/test_runpy.py | 7 + Lib/test/test_support.py | 2 + Lib/test/test_trace.py | 2 +- Makefile.pre.in | 6 + Misc/NEWS | 2 + Objects/abstract.c | 29 + Objects/dictobject.c | 10 + Objects/exceptions.c | 8 +- Python/bltinmodule.c | 2 +- Python/dynload_shlib.c | 4 - Python/freeze_importlib.py | 37 + Python/frozen.c | 3 + Python/import.c | 822 +- Python/importdl.c | 4 - Python/importlib.h | 3087 ++++++++++ Python/pystate.c | 2 + Python/pythonrun.c | 61 +- 38 files changed, 3626 insertions(+), 628 deletions(-) diff --git a/Include/abstract.h b/Include/abstract.h --- a/Include/abstract.h +++ b/Include/abstract.h @@ -339,6 +339,10 @@ PyAPI_FUNC(PyObject *) PyObject_CallMethodObjArgs(PyObject *o, PyObject *method, ...); + PyAPI_FUNC(PyObject *) _PyObject_CallMethodObjIdArgs(PyObject *o, + struct _Py_Identifier *method, + ...); + /* Call the method named m of object o with a variable number of diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -109,6 +109,8 @@ PyAPI_FUNC(PyObject *) PyDict_New(void); PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key); PyAPI_FUNC(PyObject *) PyDict_GetItemWithError(PyObject *mp, PyObject *key); +PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp, + struct _Py_Identifier *key); PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item); PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key); PyAPI_FUNC(void) PyDict_Clear(PyObject *mp); diff --git a/Include/import.h b/Include/import.h --- a/Include/import.h +++ b/Include/import.h @@ -7,6 +7,9 @@ extern "C" { #endif +PyAPI_FUNC(void) _PyImportZip_Init(void); + +PyMODINIT_FUNC PyInit_imp(void); PyAPI_FUNC(long) PyImport_GetMagicNumber(void); PyAPI_FUNC(const char *) PyImport_GetMagicTag(void); PyAPI_FUNC(PyObject *) PyImport_ExecCodeModule( diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -25,6 +25,7 @@ PyObject *modules_by_index; PyObject *sysdict; PyObject *builtins; + PyObject *importlib; PyObject *modules_reloading; PyObject *codec_search_path; @@ -33,6 +34,7 @@ int codecs_initialized; int fscodec_initialized; + #ifdef HAVE_DLOPEN int dlopenflags; #endif diff --git a/Include/pythonrun.h b/Include/pythonrun.h --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -188,7 +188,7 @@ PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void); PyAPI_FUNC(PyObject *) _PySys_Init(void); PyAPI_FUNC(void) _PyImport_Init(void); -PyAPI_FUNC(void) _PyExc_Init(void); +PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod); PyAPI_FUNC(void) _PyImportHooks_Init(void); PyAPI_FUNC(int) _PyFrame_Init(void); PyAPI_FUNC(void) _PyFloat_Init(void); diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -160,6 +160,13 @@ # Finder/loader utility code ################################################## +def verbose_message(message, *args): + """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" + if sys.flags.verbose: + if not message.startswith('#') and not message.startswith('import '): + message = '# ' + message + print(message.format(*args), file=sys.stderr) + def set_package(fxn): """Set __package__ on the returned module.""" @@ -388,9 +395,13 @@ raise ImportError("bad magic number in {}".format(fullname), name=fullname, path=bytecode_path) elif len(raw_timestamp) != 4: - raise EOFError("bad timestamp in {}".format(fullname)) + message = 'bad timestamp in {}'.format(fullname) + verbose_message(message) + raise EOFError(message) elif len(raw_size) != 4: - raise EOFError("bad size in {}".format(fullname)) + message = 'bad size in {}'.format(fullname) + verbose_message(message) + raise EOFError(message) if source_stats is not None: try: source_mtime = int(source_stats['mtime']) @@ -398,9 +409,10 @@ pass else: if _r_long(raw_timestamp) != source_mtime: - raise ImportError( - "bytecode is stale for {}".format(fullname), - name=fullname, path=bytecode_path) + message = 'bytecode is stale for {}'.format(fullname) + verbose_message(message) + raise ImportError(message, name=fullname, + path=bytecode_path) try: source_size = source_stats['size'] & 0xFFFFFFFF except KeyError: @@ -506,9 +518,13 @@ except (ImportError, EOFError): pass else: + verbose_message('{} matches {}', bytecode_path, + source_path) found = marshal.loads(bytes_data) if isinstance(found, code_type): imp._fix_co_filename(found, source_path) + verbose_message('code object from {}', + bytecode_path) return found else: msg = "Non-code object in {}" @@ -517,6 +533,7 @@ source_bytes = self.get_data(source_path) code_object = compile(source_bytes, source_path, 'exec', dont_inherit=True) + verbose_message('code object from {}', source_path) if (not sys.dont_write_bytecode and bytecode_path is not None and source_mtime is not None): # If e.g. Jython ever implements imp.cache_from_source to have @@ -528,6 +545,7 @@ data.extend(marshal.dumps(code_object)) try: self.set_data(bytecode_path, data) + verbose_message('wrote {!r}', bytecode_path) except NotImplementedError: pass return code_object @@ -596,6 +614,7 @@ return try: _write_atomic(path, data) + verbose_message('created {!r}', path) except (PermissionError, FileExistsError): # Don't worry if you can't write bytecode or someone is writing # it at the same time. @@ -615,6 +634,7 @@ bytes_data = self._bytes_from_bytecode(fullname, data, path, None) found = marshal.loads(bytes_data) if isinstance(found, code_type): + verbose_message('code object from {!r}', path) return found else: raise ImportError("Non-code object in {}".format(path), @@ -644,7 +664,9 @@ """Load an extension module.""" is_reload = fullname in sys.modules try: - return imp.load_dynamic(fullname, self._path) + module = imp.load_dynamic(fullname, self._path) + verbose_message('extension module loaded from {!r}', self._path) + return module except: if not is_reload and fullname in sys.modules: del sys.modules[fullname] @@ -953,6 +975,7 @@ elif name not in sys.modules: # The parent import may have already imported this module. loader.load_module(name) + verbose_message('import {!r} # {!r}', name, loader) # Backwards-compatibility; be nicer to skip the dict lookup. module = sys.modules[name] if parent: diff --git a/Lib/importlib/test/import_/test_path.py b/Lib/importlib/test/import_/test_path.py --- a/Lib/importlib/test/import_/test_path.py +++ b/Lib/importlib/test/import_/test_path.py @@ -87,7 +87,7 @@ class DefaultPathFinderTests(unittest.TestCase): - """Test importlib._bootstrap._DefaultPathFinder.""" + """Test _bootstrap._DefaultPathFinder.""" def test_implicit_hooks(self): # Test that the implicit path hooks are used. diff --git a/Lib/importlib/test/import_/util.py b/Lib/importlib/test/import_/util.py --- a/Lib/importlib/test/import_/util.py +++ b/Lib/importlib/test/import_/util.py @@ -1,6 +1,5 @@ import functools import importlib -import importlib._bootstrap import unittest diff --git a/Lib/importlib/test/regrtest.py b/Lib/importlib/test/regrtest.py --- a/Lib/importlib/test/regrtest.py +++ b/Lib/importlib/test/regrtest.py @@ -13,16 +13,4 @@ if __name__ == '__main__': __builtins__.__import__ = importlib.__import__ - exclude = ['--exclude', - 'test_frozen', # Does not expect __loader__ attribute - 'test_pkg', # Does not expect __loader__ attribute - 'test_pydoc', # Does not expect __loader__ attribute - ] - - # Switching on --exclude implies running all test but the ones listed, so - # only use it when one is not running an explicit test - if len(sys.argv) == 1: - # No programmatic way to specify tests to exclude - sys.argv.extend(exclude) - regrtest.main(quiet=True, verbose2=True) diff --git a/Lib/importlib/test/source/test_file_loader.py b/Lib/importlib/test/source/test_file_loader.py --- a/Lib/importlib/test/source/test_file_loader.py +++ b/Lib/importlib/test/source/test_file_loader.py @@ -1,5 +1,5 @@ +from ... import _bootstrap import importlib -from importlib import _bootstrap from .. import abc from .. import util from . import util as source_util diff --git a/Lib/importlib/test/source/test_finder.py b/Lib/importlib/test/source/test_finder.py --- a/Lib/importlib/test/source/test_finder.py +++ b/Lib/importlib/test/source/test_finder.py @@ -1,10 +1,11 @@ -from importlib import _bootstrap from .. import abc from . import util as source_util + +from importlib import _bootstrap +import errno +import os +import py_compile from test.support import make_legacy_pyc -import os -import errno -import py_compile import unittest import warnings diff --git a/Lib/importlib/test/source/test_path_hook.py b/Lib/importlib/test/source/test_path_hook.py --- a/Lib/importlib/test/source/test_path_hook.py +++ b/Lib/importlib/test/source/test_path_hook.py @@ -1,5 +1,6 @@ +from . import util as source_util + from importlib import _bootstrap -from . import util as source_util import unittest diff --git a/Lib/importlib/test/source/test_source_encoding.py b/Lib/importlib/test/source/test_source_encoding.py --- a/Lib/importlib/test/source/test_source_encoding.py +++ b/Lib/importlib/test/source/test_source_encoding.py @@ -1,6 +1,6 @@ -from importlib import _bootstrap from . import util as source_util +from importlib import _bootstrap import codecs import re import sys @@ -36,7 +36,7 @@ with open(mapping[self.module_name], 'wb') as file: file.write(source) loader = _bootstrap._SourceFileLoader(self.module_name, - mapping[self.module_name]) + mapping[self.module_name]) return loader.load_module(self.module_name) def create_source(self, encoding): diff --git a/Lib/importlib/test/util.py b/Lib/importlib/test/util.py --- a/Lib/importlib/test/util.py +++ b/Lib/importlib/test/util.py @@ -35,7 +35,7 @@ for name in names: if name in ('sys', 'marshal', 'imp'): raise ValueError( - "cannot uncache {0} as it will break _importlib".format(name)) + "cannot uncache {0}".format(name)) try: del sys.modules[name] except KeyError: diff --git a/Lib/os.py b/Lib/os.py --- a/Lib/os.py +++ b/Lib/os.py @@ -42,6 +42,8 @@ except AttributeError: return [n for n in dir(module) if n[0] != '_'] +# Any new dependencies of the os module and/or changes in path separator +# requires updating importlib as well. if 'posix' in _names: name = 'posix' linesep = '\n' diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -299,9 +299,8 @@ elif exc is SyntaxError: # A SyntaxError occurred before we could execute the module. raise ErrorDuringImport(value.filename, info) - elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport': - # The import error occurred directly in this function, - # which means there is no such module in the path. + elif exc is ImportError and value.name == path: + # No such module in the path. return None else: # Some other error occurred during the importing process. diff --git a/Lib/site.py b/Lib/site.py --- a/Lib/site.py +++ b/Lib/site.py @@ -81,7 +81,8 @@ def abs_paths(): """Set all module __file__ and __cached__ attributes to an absolute path""" for m in set(sys.modules.values()): - if hasattr(m, '__loader__'): + if (getattr(getattr(m, '__loader__', None), '__module__', None) != + '_frozen_importlib'): continue # don't mess with a PEP 302-supplied __file__ try: m.__file__ = os.path.abspath(m.__file__) diff --git a/Lib/test/test_frozen.py b/Lib/test/test_frozen.py --- a/Lib/test/test_frozen.py +++ b/Lib/test/test_frozen.py @@ -5,6 +5,12 @@ import sys class FrozenTests(unittest.TestCase): + + module_attrs = frozenset(['__builtins__', '__cached__', '__doc__', + '__file__', '__loader__', '__name__', + '__package__']) + package_attrs = frozenset(list(module_attrs) + ['__path__']) + def test_frozen(self): with captured_stdout() as stdout: try: @@ -12,7 +18,9 @@ except ImportError as x: self.fail("import __hello__ failed:" + str(x)) self.assertEqual(__hello__.initialized, True) - self.assertEqual(len(dir(__hello__)), 7, dir(__hello__)) + expect = set(self.module_attrs) + expect.add('initialized') + self.assertEqual(set(dir(__hello__)), expect) self.assertEqual(stdout.getvalue(), 'Hello world!\n') with captured_stdout() as stdout: @@ -21,10 +29,13 @@ except ImportError as x: self.fail("import __phello__ failed:" + str(x)) self.assertEqual(__phello__.initialized, True) + expect = set(self.package_attrs) + expect.add('initialized') if not "__phello__.spam" in sys.modules: - self.assertEqual(len(dir(__phello__)), 8, dir(__phello__)) + self.assertEqual(set(dir(__phello__)), expect) else: - self.assertEqual(len(dir(__phello__)), 9, dir(__phello__)) + expect.add('spam') + self.assertEqual(set(dir(__phello__)), expect) self.assertEqual(__phello__.__path__, [__phello__.__name__]) self.assertEqual(stdout.getvalue(), 'Hello world!\n') @@ -34,8 +45,13 @@ except ImportError as x: self.fail("import __phello__.spam failed:" + str(x)) self.assertEqual(__phello__.spam.initialized, True) - self.assertEqual(len(dir(__phello__.spam)), 7) - self.assertEqual(len(dir(__phello__)), 9) + spam_expect = set(self.module_attrs) + spam_expect.add('initialized') + self.assertEqual(set(dir(__phello__.spam)), spam_expect) + phello_expect = set(self.package_attrs) + phello_expect.add('initialized') + phello_expect.add('spam') + self.assertEqual(set(dir(__phello__)), phello_expect) self.assertEqual(stdout.getvalue(), 'Hello world!\n') try: diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -73,6 +73,7 @@ if TESTFN in sys.modules: del sys.modules[TESTFN] + importlib.invalidate_caches() try: try: mod = __import__(TESTFN) @@ -402,6 +403,7 @@ py_compile.compile(self.file_name, dfile=target) os.remove(self.file_name) pyc_file = make_legacy_pyc(self.file_name) + importlib.invalidate_caches() mod = self.import_module() self.assertEqual(mod.module_filename, pyc_file) self.assertEqual(mod.code_filename, target) @@ -509,7 +511,7 @@ # Check relative import fails with package set to a non-string ns = dict(__package__=object()) - self.assertRaises(ValueError, check_relative) + self.assertRaises(TypeError, check_relative) def test_absolute_import_without_future(self): # If explicit relative import syntax is used, then do not try @@ -644,6 +646,7 @@ pass unload('pep3147.foo') unload('pep3147') + importlib.invalidate_caches() m = __import__('pep3147.foo') init_pyc = imp.cache_from_source( os.path.join('pep3147', '__init__.py')) @@ -666,9 +669,11 @@ pass with open(os.path.join('pep3147', 'foo.py'), 'w'): pass + importlib.invalidate_caches() m = __import__('pep3147.foo') unload('pep3147.foo') unload('pep3147') + importlib.invalidate_caches() m = __import__('pep3147.foo') init_pyc = imp.cache_from_source( os.path.join('pep3147', '__init__.py')) diff --git a/Lib/test/test_pkg.py b/Lib/test/test_pkg.py --- a/Lib/test/test_pkg.py +++ b/Lib/test/test_pkg.py @@ -196,14 +196,15 @@ import t5 self.assertEqual(fixdir(dir(t5)), - ['__cached__', '__doc__', '__file__', '__name__', - '__package__', '__path__', 'foo', 'string', 't5']) + ['__cached__', '__doc__', '__file__', '__loader__', + '__name__', '__package__', '__path__', 'foo', + 'string', 't5']) self.assertEqual(fixdir(dir(t5.foo)), - ['__cached__', '__doc__', '__file__', '__name__', - '__package__', 'string']) + ['__cached__', '__doc__', '__file__', '__loader__', + '__name__', '__package__', 'string']) self.assertEqual(fixdir(dir(t5.string)), - ['__cached__', '__doc__', '__file__', '__name__', - '__package__', 'spam']) + ['__cached__', '__doc__', '__file__', '__loader__', + '__name__', '__package__', 'spam']) def test_6(self): hier = [ @@ -219,14 +220,14 @@ import t6 self.assertEqual(fixdir(dir(t6)), ['__all__', '__cached__', '__doc__', '__file__', - '__name__', '__package__', '__path__']) + '__loader__', '__name__', '__package__', '__path__']) s = """ import t6 from t6 import * self.assertEqual(fixdir(dir(t6)), ['__all__', '__cached__', '__doc__', '__file__', - '__name__', '__package__', '__path__', - 'eggs', 'ham', 'spam']) + '__loader__', '__name__', '__package__', + '__path__', 'eggs', 'ham', 'spam']) self.assertEqual(dir(), ['eggs', 'ham', 'self', 'spam', 't6']) """ self.run_code(s) @@ -252,19 +253,19 @@ t7, sub, subsub = None, None, None import t7 as tas self.assertEqual(fixdir(dir(tas)), - ['__cached__', '__doc__', '__file__', '__name__', - '__package__', '__path__']) + ['__cached__', '__doc__', '__file__', '__loader__', + '__name__', '__package__', '__path__']) self.assertFalse(t7) from t7 import sub as subpar self.assertEqual(fixdir(dir(subpar)), - ['__cached__', '__doc__', '__file__', '__name__', - '__package__', '__path__']) + ['__cached__', '__doc__', '__file__', '__loader__', + '__name__', '__package__', '__path__']) self.assertFalse(t7) self.assertFalse(sub) from t7.sub import subsub as subsubsub self.assertEqual(fixdir(dir(subsubsub)), - ['__cached__', '__doc__', '__file__', '__name__', - '__package__', '__path__', 'spam']) + ['__cached__', '__doc__', '__file__', '__loader__', + '__name__', '__package__', '__path__', 'spam']) self.assertFalse(t7) self.assertFalse(sub) self.assertFalse(subsub) 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 @@ -383,11 +383,10 @@ modname = 'testmod_xyzzy' testpairs = ( ('i_am_not_here', 'i_am_not_here'), - ('test.i_am_not_here_either', 'i_am_not_here_either'), - ('test.i_am_not_here.neither_am_i', 'i_am_not_here.neither_am_i'), - ('i_am_not_here.{}'.format(modname), - 'i_am_not_here.{}'.format(modname)), - ('test.{}'.format(modname), modname), + ('test.i_am_not_here_either', 'test.i_am_not_here_either'), + ('test.i_am_not_here.neither_am_i', 'test.i_am_not_here'), + ('i_am_not_here.{}'.format(modname), 'i_am_not_here'), + ('test.{}'.format(modname), 'test.{}'.format(modname)), ) sourcefn = os.path.join(TESTFN, modname) + os.extsep + "py" diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -5,6 +5,7 @@ import sys import re import tempfile +import importlib import py_compile from test.support import ( forget, make_legacy_pyc, run_unittest, unload, verbose, no_tracing, @@ -172,11 +173,13 @@ self.assertIn("x", d1) self.assertEqual(d1["x"], 1) del d1 # Ensure __loader__ entry doesn't keep file open + importlib.invalidate_caches() __import__(mod_name) os.remove(mod_fname) make_legacy_pyc(mod_fname) unload(mod_name) # In case loader caches paths if verbose: print("Running from compiled:", mod_name) + importlib.invalidate_caches() d2 = run_module(mod_name) # Read from bytecode self.assertIn("x", d2) self.assertEqual(d2["x"], 1) @@ -196,11 +199,13 @@ self.assertIn("x", d1) self.assertTrue(d1["x"] == 1) del d1 # Ensure __loader__ entry doesn't keep file open + importlib.invalidate_caches() __import__(mod_name) os.remove(mod_fname) make_legacy_pyc(mod_fname) unload(mod_name) # In case loader caches paths if verbose: print("Running from compiled:", pkg_name) + importlib.invalidate_caches() d2 = run_module(pkg_name) # Read from bytecode self.assertIn("x", d2) self.assertTrue(d2["x"] == 1) @@ -250,11 +255,13 @@ self.assertIn("sibling", d1) self.assertIn("nephew", d1) del d1 # Ensure __loader__ entry doesn't keep file open + importlib.invalidate_caches() __import__(mod_name) os.remove(mod_fname) make_legacy_pyc(mod_fname) unload(mod_name) # In case the loader caches paths if verbose: print("Running from compiled:", mod_name) + importlib.invalidate_caches() d2 = run_module(mod_name, run_name=run_name) # Read from bytecode self.assertIn("__package__", d2) self.assertTrue(d2["__package__"] == pkg_name) diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +import importlib import sys import os import unittest @@ -59,6 +60,7 @@ with open(mod_filename, 'w') as f: print('foo = 1', file=f) sys.path.insert(0, os.curdir) + importlib.invalidate_caches() try: mod = __import__(TESTFN) self.assertIn(TESTFN, sys.modules) diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -322,7 +322,7 @@ self._coverage(tracer) if os.path.exists(TESTFN): files = os.listdir(TESTFN) - self.assertEqual(files, []) + self.assertEqual(files, ['_importlib.cover']) # Ignore __import__ def test_issue9936(self): tracer = trace.Trace(trace=0, count=1) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -573,7 +573,12 @@ Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) +############################################################################ +# Importlib +Python/importlib.h: $(srcdir)/Lib/importlib/_bootstrap.py $(srcdir)/Python/freeze_importlib.py + ./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \ + $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h ############################################################################ # Special rules for object files @@ -787,6 +792,7 @@ $(srcdir)/Include/unicodeobject.h \ $(srcdir)/Include/warnings.h \ $(srcdir)/Include/weakrefobject.h \ + $(srcdir)/Python/importlib.h \ pyconfig.h \ $(PARSER_HEADERS) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #2377: Make importlib the implementation of __import__(). + - Issue #1559549: ImportError now has 'name' and 'path' attributes that are set using keyword arguments to its constructor. They are currently not set by import as they are meant for use by importlib. diff --git a/Objects/abstract.c b/Objects/abstract.c --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2377,6 +2377,35 @@ } PyObject * +_PyObject_CallMethodObjIdArgs(PyObject *callable, + struct _Py_Identifier *name, ...) +{ + PyObject *args, *tmp; + va_list vargs; + + if (callable == NULL || name == NULL) + return null_error(); + + callable = _PyObject_GetAttrId(callable, name); + if (callable == NULL) + return NULL; + + /* count the args */ + va_start(vargs, name); + args = objargs_mktuple(vargs); + va_end(vargs); + if (args == NULL) { + Py_DECREF(callable); + return NULL; + } + tmp = PyObject_Call(callable, args, NULL); + Py_DECREF(args); + Py_DECREF(callable); + + return tmp; +} + +PyObject * PyObject_CallFunctionObjArgs(PyObject *callable, ...) { PyObject *args, *tmp; diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -788,6 +788,16 @@ return ep->me_value; } +PyObject * +_PyDict_GetItemIdWithError(PyObject *dp, struct _Py_Identifier *key) +{ + PyObject *kv; + kv = _PyUnicode_FromId(key); /* borrowed */ + if (kv == NULL) + return NULL; + return PyDict_GetItemWithError(dp, kv); +} + static int dict_set_item_by_hash_or_entry(register PyObject *op, PyObject *key, Py_hash_t hash, PyDictEntry *ep, PyObject *value) diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2344,9 +2344,9 @@ #endif /* MS_WINDOWS */ void -_PyExc_Init(void) +_PyExc_Init(PyObject *bltinmod) { - PyObject *bltinmod, *bdict; + PyObject *bdict; PRE_INIT(BaseException) PRE_INIT(Exception) @@ -2414,9 +2414,6 @@ PRE_INIT(ProcessLookupError); PRE_INIT(TimeoutError); - bltinmod = PyImport_ImportModule("builtins"); - if (bltinmod == NULL) - Py_FatalError("exceptions bootstrapping error."); bdict = PyModule_GetDict(bltinmod); if (bdict == NULL) Py_FatalError("exceptions bootstrapping error."); @@ -2546,7 +2543,6 @@ Py_DECREF(args_tuple); } } - Py_DECREF(bltinmod); } void diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -187,7 +187,7 @@ static char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", 0}; PyObject *name, *globals = NULL, *locals = NULL, *fromlist = NULL; - int level = -1; + int level = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|OOOi:__import__", kwlist, &name, &globals, &locals, &fromlist, &level)) diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -115,10 +115,6 @@ dlopenflags = PyThreadState_GET()->interp->dlopenflags; #endif - if (Py_VerboseFlag) - PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname, - dlopenflags); - #ifdef __VMS /* VMS currently don't allow a pathname, use a logical name instead */ /* Concatenate 'python_module_' and shortname */ diff --git a/Python/freeze_importlib.py b/Python/freeze_importlib.py new file mode 100644 --- /dev/null +++ b/Python/freeze_importlib.py @@ -0,0 +1,37 @@ +#! /usr/bin/env python +"""Freeze importlib for use as the implementation of import.""" +import marshal + + +header = """/* Auto-generated by Python/freeze_importlib.py */""" + + +def main(input_path, output_path): + with open(input_path, 'r', encoding='utf-8') as input_file: + source = input_file.read() + + code = compile(source, '', 'exec') + + lines = [header] + lines.append('unsigned char _Py_M__importlib[] = {') + data = marshal.dumps(code) + # Code from Tools/freeze/makefreeze.py:writecode() + for i in range(0, len(data), 16): + line = [' '] + for c in data[i:i+16]: + line.append('%d,' % c) + lines.append(''.join(line)) + lines.append('};\n') + with open(output_path, 'w') as output_file: + output_file.write('\n'.join(lines)) + + +if __name__ == '__main__': + import sys + + args = sys.argv[1:] + if len(args) != 2: + print('Need to specify input and output file paths', file=sys.stderr) + sys.exit(1) + + main(*args) diff --git a/Python/frozen.c b/Python/frozen.c --- a/Python/frozen.c +++ b/Python/frozen.c @@ -2,6 +2,7 @@ /* Dummy frozen modules initializer */ #include "Python.h" +#include "importlib.h" /* In order to test the support for frozen modules, by default we define a single frozen module, __hello__. Loading it will print @@ -28,6 +29,8 @@ #define SIZE (int)sizeof(M___hello__) static struct _frozen _PyImport_FrozenModules[] = { + /* importlib */ + {"_frozen_importlib", _Py_M__importlib, (int)sizeof(_Py_M__importlib)}, /* Test module */ {"__hello__", M___hello__, SIZE}, /* Test package (negative size indicates package-ness) */ diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -203,17 +203,13 @@ void _PyImportHooks_Init(void) { - PyObject *v, *path_hooks = NULL, *zimpimport; + PyObject *v, *path_hooks = NULL; int err = 0; - /* adding sys.path_hooks and sys.path_importer_cache, setting up - zipimport */ if (PyType_Ready(&PyNullImporter_Type) < 0) goto error; - if (Py_VerboseFlag) - PySys_WriteStderr("# installing zipimport hook\n"); - + /* adding sys.path_hooks and sys.path_importer_cache */ v = PyList_New(0); if (v == NULL) goto error; @@ -234,11 +230,26 @@ err = PySys_SetObject("path_hooks", path_hooks); if (err) { error: - PyErr_Print(); - Py_FatalError("initializing sys.meta_path, sys.path_hooks, " - "path_importer_cache, or NullImporter failed" - ); + PyErr_Print(); + Py_FatalError("initializing sys.meta_path, sys.path_hooks, " + "path_importer_cache, or NullImporter failed" + ); } + Py_DECREF(path_hooks); +} + +void +_PyImportZip_Init(void) +{ + PyObject *path_hooks, *zimpimport; + int err = 0; + + path_hooks = PySys_GetObject("path_hooks"); + if (path_hooks == NULL) + goto error; + + if (Py_VerboseFlag) + PySys_WriteStderr("# installing zipimport hook\n"); zimpimport = PyImport_ImportModule("zipimport"); if (zimpimport == NULL) { @@ -261,14 +272,20 @@ /* sys.path_hooks.append(zipimporter) */ err = PyList_Append(path_hooks, zipimporter); Py_DECREF(zipimporter); - if (err) + if (err < 0) { goto error; + } if (Py_VerboseFlag) PySys_WriteStderr( "# installed zipimport hook\n"); } } - Py_DECREF(path_hooks); + + return; + + error: + PyErr_Print(); + Py_FatalError("initializing zipimport or NullImporter failed"); } /* Locking primitives to prevent parallel imports of the same module @@ -2542,8 +2559,6 @@ name); return -1; } - if (Py_VerboseFlag) - PySys_FormatStderr("import %U # builtin\n", name); mod = (*p->initfunc)(); if (mod == 0) return -1; @@ -2654,9 +2669,6 @@ ispackage = (size < 0); if (ispackage) size = -size; - if (Py_VerboseFlag) - PySys_FormatStderr("import %U # frozen%s\n", - name, ispackage ? " package" : ""); co = PyMarshal_ReadObjectFromString((char *)p->code, size); if (co == NULL) return -1; @@ -2786,130 +2798,264 @@ return result; } -/* Forward declarations for helper routines */ -static PyObject *get_parent(PyObject *globals, - PyObject **p_name, - int level); -static PyObject *load_next(PyObject *mod, PyObject *altmod, - PyObject *inputname, PyObject **p_outputname, - PyObject **p_prefix); -static int mark_miss(PyObject *name); -static int ensure_fromlist(PyObject *mod, PyObject *fromlist, - PyObject *buf, int recursive); -static PyObject * import_submodule(PyObject *mod, PyObject *name, - PyObject *fullname); - -/* The Magnum Opus of dotted-name import :-) */ - -static PyObject * -import_module_level(PyObject *name, PyObject *globals, PyObject *locals, - PyObject *fromlist, int level) + +PyObject * +PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, + PyObject *locals, PyObject *given_fromlist, + int level) { - PyObject *parent, *next, *inputname, *outputname; - PyObject *head = NULL; - PyObject *tail = NULL; - PyObject *prefix = NULL; - PyObject *result = NULL; - Py_ssize_t sep, altsep; - - if (PyUnicode_READY(name)) - return NULL; - - sep = PyUnicode_FindChar(name, SEP, 0, PyUnicode_GET_LENGTH(name), 1); - if (sep == -2) - return NULL; -#ifdef ALTSEP - altsep = PyUnicode_FindChar(name, ALTSEP, 0, PyUnicode_GET_LENGTH(name), 1); - if (altsep == -2) - return NULL; -#else - altsep = -1; -#endif - if (sep != -1 || altsep != -1) - { - PyErr_SetString(PyExc_ImportError, - "Import by filename is not supported."); - return NULL; + _Py_IDENTIFIER(__import__); + _Py_IDENTIFIER(__package__); + _Py_IDENTIFIER(__path__); + _Py_IDENTIFIER(__name__); + _Py_IDENTIFIER(_find_and_load); + _Py_IDENTIFIER(_handle_fromlist); + _Py_static_string(single_dot, "."); + PyObject *abs_name = NULL; + PyObject *builtins_import = NULL; + PyObject *final_mod = NULL; + PyObject *mod = NULL; + PyObject *package = NULL; + PyObject *globals = NULL; + PyObject *fromlist = NULL; + PyInterpreterState *interp = PyThreadState_GET()->interp; + + /* Make sure to use default values so as to not have + PyObject_CallMethodObjArgs() truncate the parameter list because of a + NULL argument. */ + if (given_globals == NULL) { + globals = PyDict_New(); + if (globals == NULL) { + goto error; + } } - - parent = get_parent(globals, &prefix, level); - if (parent == NULL) { - return NULL; + else { + /* Only have to care what given_globals is if it will be used + fortsomething. */ + if (level > 0 && !PyDict_Check(given_globals)) { + PyErr_SetString(PyExc_TypeError, "globals must be a dict"); + goto error; + } + globals = given_globals; + Py_INCREF(globals); } - if (PyUnicode_READY(prefix)) - return NULL; - - head = load_next(parent, level < 0 ? Py_None : parent, name, &outputname, - &prefix); - if (head == NULL) - goto out; - - tail = head; - Py_INCREF(tail); - - if (outputname != NULL) { - while (1) { - inputname = outputname; - next = load_next(tail, tail, inputname, &outputname, - &prefix); - Py_CLEAR(tail); - Py_CLEAR(inputname); - if (next == NULL) - goto out; - tail = next; - - if (outputname == NULL) { - break; + if (given_fromlist == NULL) { + fromlist = PyList_New(0); + if (fromlist == NULL) { + goto error; + } + } + else { + fromlist = given_fromlist; + Py_INCREF(fromlist); + } + if (name == NULL) { + PyErr_SetString(PyExc_ValueError, "Empty module name"); + goto error; + } + + /* The below code is importlib.__import__() & _gcd_import(), ported to C + for added performance. */ + + if (!PyUnicode_Check(name)) { + PyErr_SetString(PyExc_TypeError, "module name must be a string"); + goto error; + } + else if (PyUnicode_READY(name) < 0) { + goto error; + } + if (level < 0) { + PyErr_SetString(PyExc_ValueError, "level must be >= 0"); + goto error; + } + else if (level > 0) { + package = _PyDict_GetItemId(globals, &PyId___package__); + if (package != NULL && package != Py_None) { + Py_INCREF(package); + if (!PyUnicode_Check(package)) { + PyErr_SetString(PyExc_TypeError, "package must be a string"); + goto error; } } + else { + package = _PyDict_GetItemIdWithError(globals, &PyId___name__); + if (package == NULL) { + goto error; + } + else if (!PyUnicode_Check(package)) { + PyErr_SetString(PyExc_TypeError, "__name__ must be a string"); + } + Py_INCREF(package); + + if (_PyDict_GetItemId(globals, &PyId___path__) == NULL) { + PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot); + if (borrowed_dot == NULL) { + goto error; + } + PyObject *partition = PyUnicode_RPartition(package, + borrowed_dot); + Py_DECREF(package); + if (partition == NULL) { + goto error; + } + package = PyTuple_GET_ITEM(partition, 0); + Py_INCREF(package); + Py_DECREF(partition); + } + } + + if (PyDict_GetItem(interp->modules, package) == NULL) { + PyErr_Format(PyExc_SystemError, + "Parent module %R not loaded, cannot perform relative " + "import", package); + goto error; + } } - if (tail == Py_None) { - /* If tail is Py_None, both get_parent and load_next found - an empty module name: someone called __import__("") or - doctored faulty bytecode */ - PyErr_SetString(PyExc_ValueError, "Empty module name"); - goto out; + else { /* level == 0 */ + if (PyUnicode_GET_LENGTH(name) == 0) { + PyErr_SetString(PyExc_ValueError, "Empty module name"); + goto error; + } + package = Py_None; + Py_INCREF(package); } - if (fromlist != NULL) { - if (fromlist == Py_None || !PyObject_IsTrue(fromlist)) - fromlist = NULL; + if (level > 0) { + Py_ssize_t last_dot = PyUnicode_GET_LENGTH(package); + PyObject *base = NULL; + int level_up = 1; + + for (level_up = 1; level_up < level; level_up += 1) { + last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1); + if (last_dot == -2) { + goto error; + } + else if (last_dot == -1) { + PyErr_SetString(PyExc_ValueError, + "attempted relative import beyond top-level " + "package"); + goto error; + } + } + base = PyUnicode_Substring(package, 0, last_dot); + if (PyUnicode_GET_LENGTH(name) > 0) { + PyObject *borrowed_dot = NULL; + PyObject *seq = PyTuple_Pack(2, base, name); + + borrowed_dot = _PyUnicode_FromId(&single_dot); + if (borrowed_dot == NULL || seq == NULL) { + goto error; + } + + abs_name = PyUnicode_Join(borrowed_dot, seq); + Py_DECREF(seq); + if (abs_name == NULL) { + goto error; + } + } + else { + abs_name = base; + } } - - if (fromlist == NULL) { - result = head; - Py_INCREF(result); - goto out; + else { + abs_name = name; + Py_INCREF(abs_name); } - if (!ensure_fromlist(tail, fromlist, prefix, 0)) - goto out; - - result = tail; - Py_INCREF(result); - out: - Py_XDECREF(head); - Py_XDECREF(tail); - Py_XDECREF(prefix); - return result; -} - -PyObject * -PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, - PyObject *locals, PyObject *fromlist, - int level) -{ - PyObject *mod; +#if WITH_THREAD _PyImport_AcquireLock(); - mod = import_module_level(name, globals, locals, fromlist, level); +#endif + /* From this point forward, goto error_with_unlock! */ + if (PyDict_Check(globals)) { + builtins_import = _PyDict_GetItemId(globals, &PyId___import__); + } + if (builtins_import == NULL) { + builtins_import = _PyDict_GetItemId(interp->builtins, &PyId___import__); + if (builtins_import == NULL) { + Py_FatalError("__import__ missing"); + } + } + Py_INCREF(builtins_import); + + mod = PyDict_GetItem(interp->modules, abs_name); + if (mod == Py_None) { + PyErr_Format(PyExc_ImportError, + "import of %R halted; None in sys.modules", abs_name); + goto error_with_unlock; + } + else if (mod != NULL) { + Py_INCREF(mod); + } + else { + mod = _PyObject_CallMethodObjIdArgs(interp->importlib, + &PyId__find_and_load, abs_name, + builtins_import, NULL); + if (mod == NULL) { + goto error_with_unlock; + } + } + + if (PyObject_Not(fromlist)) { + if (level == 0 || PyUnicode_GET_LENGTH(name) > 0) { + PyObject *front = NULL; + PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot); + + if (borrowed_dot == NULL) { + goto error_with_unlock; + } + + PyObject *partition = PyUnicode_Partition(name, borrowed_dot); + if (partition == NULL) { + goto error_with_unlock; + } + + front = PyTuple_GET_ITEM(partition, 0); + Py_INCREF(front); + Py_DECREF(partition); + + if (level == 0) { + final_mod = PyDict_GetItemWithError(interp->modules, front); + Py_DECREF(front); + Py_XINCREF(final_mod); + } + else { + Py_ssize_t cut_off = PyUnicode_GetLength(name) - + PyUnicode_GetLength(front); + Py_ssize_t abs_name_len = PyUnicode_GetLength(abs_name); + PyObject *to_return = PyUnicode_Substring(name, 0, + abs_name_len - cut_off); + + final_mod = PyDict_GetItem(interp->modules, to_return); + Py_INCREF(final_mod); + Py_DECREF(to_return); + } + } + else { + final_mod = mod; + Py_INCREF(mod); + } + } + else { + final_mod = _PyObject_CallMethodObjIdArgs(interp->importlib, + &PyId__handle_fromlist, mod, + fromlist, builtins_import, + NULL); + } + error_with_unlock: +#if WITH_THREAD if (_PyImport_ReleaseLock() < 0) { - Py_XDECREF(mod); - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; + PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); } - return mod; +#endif + error: + Py_XDECREF(abs_name); + Py_XDECREF(builtins_import); + Py_XDECREF(mod); + Py_XDECREF(package); + Py_XDECREF(globals); + Py_XDECREF(fromlist); + return final_mod; } PyObject * @@ -2927,430 +3073,6 @@ } -/* Return the package that an import is being performed in. If globals comes - from the module foo.bar.bat (not itself a package), this returns the - sys.modules entry for foo.bar. If globals is from a package's __init__.py, - the package's entry in sys.modules is returned, as a borrowed reference. - - The name of the returned package is returned in *p_name. - - If globals doesn't come from a package or a module in a package, or a - corresponding entry is not found in sys.modules, Py_None is returned. -*/ -static PyObject * -get_parent(PyObject *globals, PyObject **p_name, int level) -{ - PyObject *nameobj; - - static PyObject *namestr = NULL; - static PyObject *pathstr = NULL; - static PyObject *pkgstr = NULL; - PyObject *pkgname, *modname, *modpath, *modules, *parent; - int orig_level = level; - - if (globals == NULL || !PyDict_Check(globals) || !level) - goto return_none; - - if (namestr == NULL) { - namestr = PyUnicode_InternFromString("__name__"); - if (namestr == NULL) - return NULL; - } - if (pathstr == NULL) { - pathstr = PyUnicode_InternFromString("__path__"); - if (pathstr == NULL) - return NULL; - } - if (pkgstr == NULL) { - pkgstr = PyUnicode_InternFromString("__package__"); - if (pkgstr == NULL) - return NULL; - } - - pkgname = PyDict_GetItem(globals, pkgstr); - - if ((pkgname != NULL) && (pkgname != Py_None)) { - /* __package__ is set, so use it */ - if (!PyUnicode_Check(pkgname)) { - PyErr_SetString(PyExc_ValueError, - "__package__ set to non-string"); - return NULL; - } - if (PyUnicode_GET_LENGTH(pkgname) == 0) { - if (level > 0) { - PyErr_SetString(PyExc_ValueError, - "Attempted relative import in non-package"); - return NULL; - } - goto return_none; - } - Py_INCREF(pkgname); - nameobj = pkgname; - } else { - /* __package__ not set, so figure it out and set it */ - modname = PyDict_GetItem(globals, namestr); - if (modname == NULL || !PyUnicode_Check(modname)) - goto return_none; - - modpath = PyDict_GetItem(globals, pathstr); - if (modpath != NULL) { - /* __path__ is set, so modname is already the package name */ - int error; - - error = PyDict_SetItem(globals, pkgstr, modname); - if (error) { - PyErr_SetString(PyExc_ValueError, - "Could not set __package__"); - return NULL; - } - Py_INCREF(modname); - nameobj = modname; - } else { - /* Normal module, so work out the package name if any */ - Py_ssize_t len; - len = PyUnicode_FindChar(modname, '.', - 0, PyUnicode_GET_LENGTH(modname), -1); - if (len == -2) - return NULL; - if (len < 0) { - if (level > 0) { - PyErr_SetString(PyExc_ValueError, - "Attempted relative import in non-package"); - return NULL; - } - if (PyDict_SetItem(globals, pkgstr, Py_None)) { - PyErr_SetString(PyExc_ValueError, - "Could not set __package__"); - return NULL; - } - goto return_none; - } - pkgname = PyUnicode_Substring(modname, 0, len); - if (pkgname == NULL) - return NULL; - if (PyDict_SetItem(globals, pkgstr, pkgname)) { - Py_DECREF(pkgname); - PyErr_SetString(PyExc_ValueError, - "Could not set __package__"); - return NULL; - } - nameobj = pkgname; - } - } - if (level > 1) { - Py_ssize_t dot, end = PyUnicode_GET_LENGTH(nameobj); - PyObject *newname; - while (--level > 0) { - dot = PyUnicode_FindChar(nameobj, '.', 0, end, -1); - if (dot == -2) { - Py_DECREF(nameobj); - return NULL; - } - if (dot < 0) { - Py_DECREF(nameobj); - PyErr_SetString(PyExc_ValueError, - "Attempted relative import beyond " - "toplevel package"); - return NULL; - } - end = dot; - } - newname = PyUnicode_Substring(nameobj, 0, end); - Py_DECREF(nameobj); - if (newname == NULL) - return NULL; - nameobj = newname; - } - - modules = PyImport_GetModuleDict(); - parent = PyDict_GetItem(modules, nameobj); - if (parent == NULL) { - int err; - - if (orig_level >= 1) { - PyErr_Format(PyExc_SystemError, - "Parent module %R not loaded, " - "cannot perform relative import", nameobj); - Py_DECREF(nameobj); - return NULL; - } - - err = PyErr_WarnFormat( - PyExc_RuntimeWarning, 1, - "Parent module %R not found while handling absolute import", - nameobj); - Py_DECREF(nameobj); - if (err) - return NULL; - - goto return_none; - } - *p_name = nameobj; - return parent; - /* We expect, but can't guarantee, if parent != None, that: - - parent.__name__ == name - - parent.__dict__ is globals - If this is violated... Who cares? */ - -return_none: - nameobj = PyUnicode_New(0, 0); - if (nameobj == NULL) - return NULL; - *p_name = nameobj; - return Py_None; -} - -/* altmod is either None or same as mod */ -static PyObject * -load_next(PyObject *mod, PyObject *altmod, - PyObject *inputname, PyObject **p_outputname, - PyObject **p_prefix) -{ - Py_ssize_t dot; - Py_ssize_t len; - PyObject *fullname, *name = NULL, *result; - - *p_outputname = NULL; - - len = PyUnicode_GET_LENGTH(inputname); - if (len == 0) { - /* completely empty module name should only happen in - 'from . import' (or '__import__("")')*/ - Py_INCREF(mod); - return mod; - } - - - dot = PyUnicode_FindChar(inputname, '.', 0, len, 1); - if (dot >= 0) { - len = dot; - if (len == 0) { - PyErr_SetString(PyExc_ValueError, - "Empty module name"); - goto error; - } - } - - /* name = inputname[:len] */ - name = PyUnicode_Substring(inputname, 0, len); - if (name == NULL) - goto error; - - if (PyUnicode_GET_LENGTH(*p_prefix)) { - /* fullname = prefix + "." + name */ - fullname = PyUnicode_FromFormat("%U.%U", *p_prefix, name); - if (fullname == NULL) - goto error; - } - else { - fullname = name; - Py_INCREF(fullname); - } - - result = import_submodule(mod, name, fullname); - Py_DECREF(*p_prefix); - /* Transfer reference. */ - *p_prefix = fullname; - if (result == Py_None && altmod != mod) { - Py_DECREF(result); - /* Here, altmod must be None and mod must not be None */ - result = import_submodule(altmod, name, name); - if (result != NULL && result != Py_None) { - if (mark_miss(*p_prefix) != 0) { - Py_DECREF(result); - goto error; - } - Py_DECREF(*p_prefix); - *p_prefix = name; - Py_INCREF(*p_prefix); - } - } - if (result == NULL) - goto error; - - if (result == Py_None) { - Py_DECREF(result); - PyErr_Format(PyExc_ImportError, - "No module named %R", inputname); - goto error; - } - - if (dot >= 0) { - *p_outputname = PyUnicode_Substring(inputname, dot+1, - PyUnicode_GET_LENGTH(inputname)); - if (*p_outputname == NULL) { - Py_DECREF(result); - goto error; - } - } - - Py_DECREF(name); - return result; - -error: - Py_XDECREF(name); - return NULL; -} - -static int -mark_miss(PyObject *name) -{ - PyObject *modules = PyImport_GetModuleDict(); - return PyDict_SetItem(modules, name, Py_None); -} - -static int -ensure_fromlist(PyObject *mod, PyObject *fromlist, PyObject *name, - int recursive) -{ - int i; - PyObject *fullname; - Py_ssize_t fromlist_len; - - if (!_PyObject_HasAttrId(mod, &PyId___path__)) - return 1; - - fromlist_len = PySequence_Size(fromlist); - - for (i = 0; i < fromlist_len; i++) { - PyObject *item = PySequence_GetItem(fromlist, i); - int hasit; - if (item == NULL) - return 0; - if (!PyUnicode_Check(item)) { - PyErr_SetString(PyExc_TypeError, - "Item in ``from list'' not a string"); - Py_DECREF(item); - return 0; - } - if (PyUnicode_READ_CHAR(item, 0) == '*') { - PyObject *all; - _Py_IDENTIFIER(__all__); - Py_DECREF(item); - /* See if the package defines __all__ */ - if (recursive) - continue; /* Avoid endless recursion */ - all = _PyObject_GetAttrId(mod, &PyId___all__); - if (all == NULL) - PyErr_Clear(); - else { - int ret = ensure_fromlist(mod, all, name, 1); - Py_DECREF(all); - if (!ret) - return 0; - } - continue; - } - hasit = PyObject_HasAttr(mod, item); - if (!hasit) { - PyObject *submod; - fullname = PyUnicode_FromFormat("%U.%U", name, item); - if (fullname != NULL) { - submod = import_submodule(mod, item, fullname); - Py_DECREF(fullname); - } - else - submod = NULL; - Py_XDECREF(submod); - if (submod == NULL) { - Py_DECREF(item); - return 0; - } - } - Py_DECREF(item); - } - - return 1; -} - -static int -add_submodule(PyObject *mod, PyObject *submod, PyObject *fullname, - PyObject *subname, PyObject *modules) -{ - if (mod == Py_None) - return 1; - /* Irrespective of the success of this load, make a - reference to it in the parent package module. A copy gets - saved in the modules dictionary under the full name, so get a - reference from there, if need be. (The exception is when the - load failed with a SyntaxError -- then there's no trace in - sys.modules. In that case, of course, do nothing extra.) */ - if (submod == NULL) { - submod = PyDict_GetItem(modules, fullname); - if (submod == NULL) - return 1; - } - if (PyModule_Check(mod)) { - /* We can't use setattr here since it can give a - * spurious warning if the submodule name shadows a - * builtin name */ - PyObject *dict = PyModule_GetDict(mod); - if (!dict) - return 0; - if (PyDict_SetItem(dict, subname, submod) < 0) - return 0; - } - else { - if (PyObject_SetAttr(mod, subname, submod) < 0) - return 0; - } - return 1; -} - -static PyObject * -import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) -{ - PyObject *modules = PyImport_GetModuleDict(); - PyObject *m = NULL, *bufobj, *path_list, *loader; - struct filedescr *fdp; - FILE *fp; - - /* Require: - if mod == None: subname == fullname - else: mod.__name__ + "." + subname == fullname - */ - - if ((m = PyDict_GetItem(modules, fullname)) != NULL) { - Py_INCREF(m); - return m; - } - - if (mod == Py_None) - path_list = NULL; - else { - path_list = _PyObject_GetAttrId(mod, &PyId___path__); - if (path_list == NULL) { - PyErr_Clear(); - Py_INCREF(Py_None); - return Py_None; - } - } - - fdp = find_module(fullname, subname, path_list, - &bufobj, &fp, &loader); - Py_XDECREF(path_list); - if (fdp == NULL) { - if (!PyErr_ExceptionMatches(PyExc_ImportError)) - return NULL; - PyErr_Clear(); - Py_INCREF(Py_None); - return Py_None; - } - m = load_module(fullname, fp, bufobj, fdp->type, loader); - Py_XDECREF(bufobj); - Py_XDECREF(loader); - if (fp) - fclose(fp); - if (m == NULL) - return NULL; - if (!add_submodule(mod, m, fullname, subname, modules)) { - Py_XDECREF(m); - return NULL; - } - return m; -} - - /* Re-import a module of any kind and return its module object, WITH INCREMENTED REFERENCE COUNT */ diff --git a/Python/importdl.c b/Python/importdl.c --- a/Python/importdl.c +++ b/Python/importdl.c @@ -106,10 +106,6 @@ if (_PyImport_FixupExtensionObject(m, name, path) < 0) goto error; - if (Py_VerboseFlag) - PySys_FormatStderr( - "import %U # dynamically loaded from %R\n", - name, path); Py_DECREF(nameascii); return m; diff --git a/Python/importlib.h b/Python/importlib.h new file mode 100644 --- /dev/null +++ b/Python/importlib.h @@ -0,0 +1,3087 @@ +/* Auto-generated by Python/freeze_importlib.py */ +unsigned char _Py_M__importlib[] = { + 99,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0, + 0,64,0,0,0,115,239,2,0,0,100,0,0,90,0,0, + 100,99,0,90,1,0,100,4,0,100,5,0,132,0,0,90, + 2,0,100,6,0,100,7,0,132,0,0,90,3,0,100,8, + 0,100,9,0,132,0,0,90,4,0,100,10,0,100,11,0, + 132,0,0,90,5,0,100,12,0,100,13,0,132,0,0,90, + 6,0,100,14,0,100,15,0,132,0,0,90,7,0,100,16, + 0,100,17,0,132,0,0,90,8,0,100,18,0,100,19,0, + 132,0,0,90,9,0,100,20,0,100,21,0,132,0,0,90, + 10,0,100,22,0,100,23,0,132,0,0,90,11,0,100,24, + 0,100,25,0,132,0,0,90,12,0,100,26,0,100,27,0, + 132,0,0,90,13,0,101,14,0,101,13,0,106,15,0,131, + 1,0,90,16,0,100,28,0,100,29,0,132,0,0,90,17, + 0,100,30,0,100,31,0,132,0,0,90,18,0,100,32,0, + 100,33,0,132,0,0,90,19,0,100,34,0,100,35,0,132, + 0,0,90,20,0,100,36,0,100,37,0,132,0,0,90,21, + 0,100,38,0,100,39,0,132,0,0,90,22,0,100,40,0, + 100,41,0,132,0,0,90,23,0,100,42,0,100,43,0,132, + 0,0,90,24,0,71,100,44,0,100,45,0,132,0,0,100, + 45,0,131,2,0,90,25,0,71,100,46,0,100,47,0,132, + 0,0,100,47,0,131,2,0,90,26,0,71,100,48,0,100, + 49,0,132,0,0,100,49,0,131,2,0,90,27,0,71,100, + 50,0,100,51,0,132,0,0,100,51,0,101,27,0,131,3, + 0,90,28,0,71,100,52,0,100,53,0,132,0,0,100,53, + 0,131,2,0,90,29,0,71,100,54,0,100,55,0,132,0, + 0,100,55,0,101,29,0,101,28,0,131,4,0,90,30,0, + 71,100,56,0,100,57,0,132,0,0,100,57,0,101,29,0, + 101,27,0,131,4,0,90,31,0,71,100,58,0,100,59,0, + 132,0,0,100,59,0,131,2,0,90,32,0,71,100,60,0, + 100,61,0,132,0,0,100,61,0,131,2,0,90,33,0,71, + 100,62,0,100,63,0,132,0,0,100,63,0,131,2,0,90, + 34,0,71,100,64,0,100,65,0,132,0,0,100,65,0,131, + 2,0,90,35,0,71,100,66,0,100,67,0,132,0,0,100, + 67,0,131,2,0,90,36,0,71,100,68,0,100,69,0,132, + 0,0,100,69,0,131,2,0,90,37,0,100,70,0,100,71, + 0,132,0,0,90,38,0,101,38,0,90,39,0,71,100,72, + 0,100,73,0,132,0,0,100,73,0,101,33,0,131,3,0, + 90,40,0,71,100,74,0,100,75,0,132,0,0,100,75,0, + 131,2,0,90,41,0,100,76,0,100,77,0,132,0,0,90, + 42,0,100,78,0,100,79,0,132,0,0,90,43,0,100,80, + 0,100,81,0,132,0,0,90,44,0,101,25,0,101,26,0, + 101,40,0,103,3,0,90,45,0,100,82,0,90,46,0,100, + 83,0,100,84,0,132,0,0,90,47,0,100,98,0,100,85, + 0,100,86,0,100,87,0,132,2,0,90,49,0,100,88,0, + 100,89,0,132,0,0,90,50,0,100,90,0,100,91,0,132, + 0,0,90,51,0,105,0,0,105,0,0,103,0,0,100,85, + 0,100,92,0,100,93,0,132,4,0,90,52,0,100,94,0, + 100,95,0,132,0,0,90,53,0,100,96,0,100,97,0,132, + 0,0,90,54,0,100,98,0,83,40,100,0,0,0,117,83, + 1,0,0,67,111,114,101,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,111,102,32,105,109,112,111,114,116, + 46,10,10,84,104,105,115,32,109,111,100,117,108,101,32,105, + 115,32,78,79,84,32,109,101,97,110,116,32,116,111,32,98, + 101,32,100,105,114,101,99,116,108,121,32,105,109,112,111,114, + 116,101,100,33,32,73,116,32,104,97,115,32,98,101,101,110, + 32,100,101,115,105,103,110,101,100,32,115,117,99,104,10,116, + 104,97,116,32,105,116,32,99,97,110,32,98,101,32,98,111, + 111,116,115,116,114,97,112,112,101,100,32,105,110,116,111,32, + 80,121,116,104,111,110,32,97,115,32,116,104,101,32,105,109, + 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, + 105,109,112,111,114,116,46,32,65,115,10,115,117,99,104,32, + 105,116,32,114,101,113,117,105,114,101,115,32,116,104,101,32, + 105,110,106,101,99,116,105,111,110,32,111,102,32,115,112,101, + 99,105,102,105,99,32,109,111,100,117,108,101,115,32,97,110, + 100,32,97,116,116,114,105,98,117,116,101,115,32,105,110,32, + 111,114,100,101,114,32,116,111,10,119,111,114,107,46,32,79, + 110,101,32,115,104,111,117,108,100,32,117,115,101,32,105,109, + 112,111,114,116,108,105,98,32,97,115,32,116,104,101,32,112, + 117,98,108,105,99,45,102,97,99,105,110,103,32,118,101,114, + 115,105,111,110,32,111,102,32,116,104,105,115,32,109,111,100, + 117,108,101,46,10,10,117,3,0,0,0,119,105,110,117,6, + 0,0,0,99,121,103,119,105,110,117,6,0,0,0,100,97, + 114,119,105,110,99,0,0,0,0,0,0,0,0,1,0,0, + 0,4,0,0,0,67,0,0,0,115,58,0,0,0,116,0, + 0,116,1,0,116,2,0,106,3,0,106,4,0,116,5,0, + 131,2,0,131,1,0,114,42,0,100,1,0,100,2,0,132, + 0,0,125,0,0,110,12,0,100,3,0,100,2,0,132,0, + 0,125,0,0,124,0,0,83,40,4,0,0,0,78,99,0, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,83, + 0,0,0,115,13,0,0,0,100,1,0,116,0,0,106,1, + 0,107,6,0,83,40,2,0,0,0,117,53,0,0,0,84, + 114,117,101,32,105,102,32,102,105,108,101,110,97,109,101,115, + 32,109,117,115,116,32,98,101,32,99,104,101,99,107,101,100, + 32,99,97,115,101,45,105,110,115,101,110,115,105,116,105,118, + 101,108,121,46,115,12,0,0,0,80,89,84,72,79,78,67, + 65,83,69,79,75,40,2,0,0,0,117,3,0,0,0,95, + 111,115,117,7,0,0,0,101,110,118,105,114,111,110,40,0, + 0,0,0,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 11,0,0,0,95,114,101,108,97,120,95,99,97,115,101,27, + 0,0,0,115,2,0,0,0,0,2,117,37,0,0,0,95, + 109,97,107,101,95,114,101,108,97,120,95,99,97,115,101,46, + 60,108,111,99,97,108,115,62,46,95,114,101,108,97,120,95, + 99,97,115,101,99,0,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,83,0,0,0,115,4,0,0,0,100,1, + 0,83,40,2,0,0,0,117,53,0,0,0,84,114,117,101, + 32,105,102,32,102,105,108,101,110,97,109,101,115,32,109,117, + 115,116,32,98,101,32,99,104,101,99,107,101,100,32,99,97, + 115,101,45,105,110,115,101,110,115,105,116,105,118,101,108,121, + 46,70,40,1,0,0,0,117,5,0,0,0,70,97,108,115, + 101,40,0,0,0,0,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,11,0,0,0,95,114,101,108,97,120,95,99,97, + 115,101,31,0,0,0,115,2,0,0,0,0,2,40,6,0, + 0,0,117,3,0,0,0,97,110,121,117,3,0,0,0,109, + 97,112,117,3,0,0,0,115,121,115,117,8,0,0,0,112, + 108,97,116,102,111,114,109,117,10,0,0,0,115,116,97,114, + 116,115,119,105,116,104,117,26,0,0,0,67,65,83,69,95, + 73,78,83,69,78,83,73,84,73,86,69,95,80,76,65,84, + 70,79,82,77,83,40,1,0,0,0,117,11,0,0,0,95, + 114,101,108,97,120,95,99,97,115,101,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,16,0,0,0,95,109,97,107,101, + 95,114,101,108,97,120,95,99,97,115,101,25,0,0,0,115, + 8,0,0,0,0,1,27,1,15,4,12,3,117,16,0,0, + 0,95,109,97,107,101,95,114,101,108,97,120,95,99,97,115, + 101,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,67,0,0,0,115,108,0,0,0,116,0,0,124,0, + 0,131,1,0,125,0,0,103,0,0,125,1,0,124,1,0, + 106,1,0,124,0,0,100,1,0,64,131,1,0,1,124,1, + 0,106,1,0,124,0,0,100,2,0,63,100,1,0,64,131, + 1,0,1,124,1,0,106,1,0,124,0,0,100,3,0,63, + 100,1,0,64,131,1,0,1,124,1,0,106,1,0,124,0, + 0,100,4,0,63,100,1,0,64,131,1,0,1,116,2,0, + 124,1,0,131,1,0,83,40,5,0,0,0,117,111,0,0, + 0,67,111,110,118,101,114,116,32,97,32,51,50,45,98,105, + 116,32,105,110,116,101,103,101,114,32,116,111,32,108,105,116, + 116,108,101,45,101,110,100,105,97,110,46,10,10,32,32,32, + 32,88,88,88,32,84,101,109,112,111,114,97,114,121,32,117, + 110,116,105,108,32,109,97,114,115,104,97,108,39,115,32,108, + 111,110,103,32,102,117,110,99,116,105,111,110,115,32,97,114, + 101,32,101,120,112,111,115,101,100,46,10,10,32,32,32,32, + 105,255,0,0,0,105,8,0,0,0,105,16,0,0,0,105, + 24,0,0,0,40,3,0,0,0,117,3,0,0,0,105,110, + 116,117,6,0,0,0,97,112,112,101,110,100,117,9,0,0, + 0,98,121,116,101,97,114,114,97,121,40,2,0,0,0,117, + 1,0,0,0,120,117,9,0,0,0,105,110,116,95,98,121, + 116,101,115,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 7,0,0,0,95,119,95,108,111,110,103,38,0,0,0,115, + 14,0,0,0,0,6,12,1,6,1,17,1,21,1,21,1, + 21,1,117,7,0,0,0,95,119,95,108,111,110,103,99,1, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,68,0,0,0,124,0,0,100,1,0,25,125, + 1,0,124,1,0,124,0,0,100,2,0,25,100,3,0,62, + 79,125,1,0,124,1,0,124,0,0,100,4,0,25,100,5, + 0,62,79,125,1,0,124,1,0,124,0,0,100,6,0,25, + 100,7,0,62,79,125,1,0,124,1,0,83,40,8,0,0, + 0,117,115,0,0,0,67,111,110,118,101,114,116,32,52,32, + 98,121,116,101,115,32,105,110,32,108,105,116,116,108,101,45, + 101,110,100,105,97,110,32,116,111,32,97,110,32,105,110,116, + 101,103,101,114,46,10,10,32,32,32,32,88,88,88,32,84, + 101,109,112,111,114,97,114,121,32,117,110,116,105,108,32,109, + 97,114,115,104,97,108,39,115,32,108,111,110,103,32,102,117, + 110,99,116,105,111,110,32,97,114,101,32,101,120,112,111,115, + 101,100,46,10,10,32,32,32,32,105,0,0,0,0,105,1, + 0,0,0,105,8,0,0,0,105,2,0,0,0,105,16,0, + 0,0,105,3,0,0,0,105,24,0,0,0,40,0,0,0, + 0,40,2,0,0,0,117,9,0,0,0,105,110,116,95,98, + 121,116,101,115,117,1,0,0,0,120,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,7,0,0,0,95,114,95,108,111, + 110,103,54,0,0,0,115,10,0,0,0,0,6,10,1,18, + 1,18,1,18,1,117,7,0,0,0,95,114,95,108,111,110, + 103,99,0,0,0,0,0,0,0,0,1,0,0,0,3,0, + 0,0,71,0,0,0,115,26,0,0,0,116,0,0,106,1, + 0,100,1,0,100,2,0,132,0,0,124,0,0,68,131,1, + 0,131,1,0,83,40,3,0,0,0,117,29,0,0,0,82, + 101,112,108,97,99,101,109,101,110,116,32,102,111,114,32,111, + 115,46,112,97,116,104,46,106,111,105,110,46,99,1,0,0, + 0,0,0,0,0,2,0,0,0,5,0,0,0,115,0,0, + 0,115,65,0,0,0,124,0,0,93,55,0,125,1,0,124, + 1,0,114,3,0,124,1,0,106,0,0,116,1,0,131,1, + 0,114,53,0,124,1,0,100,0,0,116,2,0,116,1,0, + 131,1,0,11,133,2,0,25,110,3,0,124,1,0,86,1, + 113,3,0,100,0,0,83,40,1,0,0,0,78,40,3,0, + 0,0,117,8,0,0,0,101,110,100,115,119,105,116,104,117, + 8,0,0,0,112,97,116,104,95,115,101,112,117,3,0,0, + 0,108,101,110,40,2,0,0,0,117,2,0,0,0,46,48, + 117,1,0,0,0,120,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,9,0,0,0,60,103,101,110,101,120,112,114,62, + 71,0,0,0,115,2,0,0,0,6,1,117,29,0,0,0, + 95,112,97,116,104,95,106,111,105,110,46,60,108,111,99,97, + 108,115,62,46,60,103,101,110,101,120,112,114,62,40,2,0, + 0,0,117,8,0,0,0,112,97,116,104,95,115,101,112,117, + 4,0,0,0,106,111,105,110,40,1,0,0,0,117,4,0, + 0,0,97,114,103,115,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,10,0,0,0,95,112,97,116,104,95,106,111,105, + 110,69,0,0,0,115,4,0,0,0,0,2,15,1,117,10, + 0,0,0,95,112,97,116,104,95,106,111,105,110,99,1,0, + 0,0,0,0,0,0,1,0,0,0,11,0,0,0,67,0, + 0,0,115,50,0,0,0,121,17,0,116,0,0,106,1,0, + 124,0,0,131,1,0,1,87,110,22,0,4,116,2,0,107, + 10,0,114,41,0,1,1,1,100,2,0,83,89,110,5,0, + 88,100,3,0,83,100,1,0,83,40,4,0,0,0,117,31, + 0,0,0,82,101,112,108,97,99,101,109,101,110,116,32,102, + 111,114,32,111,115,46,112,97,116,104,46,101,120,105,115,116, + 115,46,78,70,84,40,5,0,0,0,117,3,0,0,0,95, + 111,115,117,4,0,0,0,115,116,97,116,117,7,0,0,0, + 79,83,69,114,114,111,114,117,5,0,0,0,70,97,108,115, + 101,117,4,0,0,0,84,114,117,101,40,1,0,0,0,117, + 4,0,0,0,112,97,116,104,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,12,0,0,0,95,112,97,116,104,95,101, + 120,105,115,116,115,75,0,0,0,115,10,0,0,0,0,2, + 3,1,17,1,13,1,9,2,117,12,0,0,0,95,112,97, + 116,104,95,101,120,105,115,116,115,99,2,0,0,0,0,0, + 0,0,3,0,0,0,11,0,0,0,67,0,0,0,115,61, + 0,0,0,121,19,0,116,0,0,106,1,0,124,0,0,131, + 1,0,125,2,0,87,110,22,0,4,116,2,0,107,10,0, + 114,43,0,1,1,1,100,2,0,83,89,110,1,0,88,124, + 2,0,106,4,0,100,1,0,64,124,1,0,107,2,0,83, + 40,3,0,0,0,117,49,0,0,0,84,101,115,116,32,119, + 104,101,116,104,101,114,32,116,104,101,32,112,97,116,104,32, + 105,115,32,116,104,101,32,115,112,101,99,105,102,105,101,100, + 32,109,111,100,101,32,116,121,112,101,46,105,0,240,0,0, + 70,40,5,0,0,0,117,3,0,0,0,95,111,115,117,4, + 0,0,0,115,116,97,116,117,7,0,0,0,79,83,69,114, + 114,111,114,117,5,0,0,0,70,97,108,115,101,117,7,0, + 0,0,115,116,95,109,111,100,101,40,3,0,0,0,117,4, + 0,0,0,112,97,116,104,117,4,0,0,0,109,111,100,101, + 117,9,0,0,0,115,116,97,116,95,105,110,102,111,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,18,0,0,0,95, + 112,97,116,104,95,105,115,95,109,111,100,101,95,116,121,112, + 101,85,0,0,0,115,10,0,0,0,0,2,3,1,19,1, + 13,1,9,1,117,18,0,0,0,95,112,97,116,104,95,105, + 115,95,109,111,100,101,95,116,121,112,101,99,1,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 115,13,0,0,0,116,0,0,124,0,0,100,1,0,131,2, + 0,83,40,2,0,0,0,117,31,0,0,0,82,101,112,108, + 97,99,101,109,101,110,116,32,102,111,114,32,111,115,46,112, + 97,116,104,46,105,115,102,105,108,101,46,105,0,128,0,0, + 40,1,0,0,0,117,18,0,0,0,95,112,97,116,104,95, + 105,115,95,109,111,100,101,95,116,121,112,101,40,1,0,0, + 0,117,4,0,0,0,112,97,116,104,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,12,0,0,0,95,112,97,116,104, + 95,105,115,102,105,108,101,95,0,0,0,115,2,0,0,0, + 0,2,117,12,0,0,0,95,112,97,116,104,95,105,115,102, + 105,108,101,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,34,0,0,0,124,0,0, + 115,21,0,116,0,0,106,1,0,131,0,0,125,0,0,110, + 0,0,116,2,0,124,0,0,100,1,0,131,2,0,83,40, + 2,0,0,0,117,30,0,0,0,82,101,112,108,97,99,101, + 109,101,110,116,32,102,111,114,32,111,115,46,112,97,116,104, + 46,105,115,100,105,114,46,105,0,64,0,0,40,3,0,0, + 0,117,3,0,0,0,95,111,115,117,6,0,0,0,103,101, + 116,99,119,100,117,18,0,0,0,95,112,97,116,104,95,105, + 115,95,109,111,100,101,95,116,121,112,101,40,1,0,0,0, + 117,4,0,0,0,112,97,116,104,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,11,0,0,0,95,112,97,116,104,95, + 105,115,100,105,114,101,0,0,0,115,6,0,0,0,0,2, + 6,1,15,1,117,11,0,0,0,95,112,97,116,104,95,105, + 115,100,105,114,99,2,0,0,0,0,0,0,0,3,0,0, + 0,5,0,0,0,67,0,0,0,115,75,0,0,0,120,68, + 0,116,0,0,124,1,0,131,1,0,68,93,42,0,125,2, + 0,124,0,0,106,1,0,124,2,0,131,1,0,114,13,0, + 124,0,0,100,1,0,116,2,0,124,2,0,131,1,0,11, + 133,2,0,25,83,113,13,0,87,116,3,0,100,2,0,131, + 1,0,130,1,0,100,1,0,83,40,3,0,0,0,117,38, + 0,0,0,82,101,112,108,97,99,101,109,101,110,116,32,102, + 111,114,32,111,115,46,112,97,116,104,46,115,112,108,105,116, + 101,120,116,40,41,91,48,93,46,78,117,33,0,0,0,112, + 97,116,104,32,105,115,32,110,111,116,32,111,102,32,116,104, + 101,32,115,112,101,99,105,102,105,101,100,32,116,121,112,101, + 40,4,0,0,0,117,12,0,0,0,95,115,117,102,102,105, + 120,95,108,105,115,116,117,8,0,0,0,101,110,100,115,119, + 105,116,104,117,3,0,0,0,108,101,110,117,10,0,0,0, + 86,97,108,117,101,69,114,114,111,114,40,3,0,0,0,117, + 4,0,0,0,112,97,116,104,117,8,0,0,0,101,120,116, + 95,116,121,112,101,117,6,0,0,0,115,117,102,102,105,120, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,17,0,0, + 0,95,112,97,116,104,95,119,105,116,104,111,117,116,95,101, + 120,116,108,0,0,0,115,8,0,0,0,0,2,19,1,15, + 1,25,2,117,17,0,0,0,95,112,97,116,104,95,119,105, + 116,104,111,117,116,95,101,120,116,99,1,0,0,0,0,0, + 0,0,1,0,0,0,11,0,0,0,67,0,0,0,115,101, + 0,0,0,124,0,0,115,21,0,116,0,0,106,1,0,131, + 0,0,125,0,0,110,0,0,121,17,0,116,0,0,106,2, + 0,124,0,0,131,1,0,83,87,110,56,0,4,116,3,0, + 107,10,0,114,96,0,1,1,1,124,0,0,106,4,0,100, + 1,0,131,1,0,114,73,0,124,0,0,83,116,5,0,116, + 0,0,106,1,0,131,0,0,124,0,0,131,2,0,83,89, + 110,1,0,88,100,2,0,83,40,3,0,0,0,117,32,0, + 0,0,82,101,112,108,97,99,101,109,101,110,116,32,102,111, + 114,32,111,115,46,112,97,116,104,46,97,98,115,112,97,116, + 104,46,117,1,0,0,0,47,78,40,6,0,0,0,117,3, + 0,0,0,95,111,115,117,6,0,0,0,103,101,116,99,119, + 100,117,16,0,0,0,95,103,101,116,102,117,108,108,112,97, + 116,104,110,97,109,101,117,14,0,0,0,65,116,116,114,105, + 98,117,116,101,69,114,114,111,114,117,10,0,0,0,115,116, + 97,114,116,115,119,105,116,104,117,10,0,0,0,95,112,97, + 116,104,95,106,111,105,110,40,1,0,0,0,117,4,0,0, + 0,112,97,116,104,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,14,0,0,0,95,112,97,116,104,95,97,98,115,111, + 108,117,116,101,117,0,0,0,115,16,0,0,0,0,2,6, + 1,15,1,3,1,17,1,13,1,15,1,4,2,117,14,0, + 0,0,95,112,97,116,104,95,97,98,115,111,108,117,116,101, + 99,2,0,0,0,0,0,0,0,5,0,0,0,17,0,0, + 0,67,0,0,0,115,188,0,0,0,100,1,0,106,0,0, + 124,0,0,116,1,0,124,0,0,131,1,0,131,2,0,125, + 2,0,116,2,0,106,3,0,124,2,0,116,2,0,106,4, + 0,116,2,0,106,5,0,66,116,2,0,106,6,0,66,100, + 2,0,131,3,0,125,3,0,121,60,0,116,7,0,106,8, + 0,124,3,0,100,3,0,131,2,0,143,20,0,125,4,0, + 124,4,0,106,9,0,124,1,0,131,1,0,1,87,100,4, + 0,81,88,116,2,0,106,10,0,124,2,0,124,0,0,131, + 2,0,1,87,110,59,0,4,116,11,0,107,10,0,114,183, + 0,1,1,1,121,17,0,116,2,0,106,12,0,124,2,0, + 131,1,0,1,87,110,18,0,4,116,11,0,107,10,0,114, + 175,0,1,1,1,89,110,1,0,88,130,0,0,89,110,1, + 0,88,100,4,0,83,40,5,0,0,0,117,162,0,0,0, + 66,101,115,116,45,101,102,102,111,114,116,32,102,117,110,99, + 116,105,111,110,32,116,111,32,119,114,105,116,101,32,100,97, + 116,97,32,116,111,32,97,32,112,97,116,104,32,97,116,111, + 109,105,99,97,108,108,121,46,10,32,32,32,32,66,101,32, + 112,114,101,112,97,114,101,100,32,116,111,32,104,97,110,100, + 108,101,32,97,32,70,105,108,101,69,120,105,115,116,115,69, + 114,114,111,114,32,105,102,32,99,111,110,99,117,114,114,101, + 110,116,32,119,114,105,116,105,110,103,32,111,102,32,116,104, + 101,10,32,32,32,32,116,101,109,112,111,114,97,114,121,32, + 102,105,108,101,32,105,115,32,97,116,116,101,109,112,116,101, + 100,46,117,5,0,0,0,123,125,46,123,125,105,182,1,0, + 0,117,2,0,0,0,119,98,78,40,13,0,0,0,117,6, + 0,0,0,102,111,114,109,97,116,117,2,0,0,0,105,100, + 117,3,0,0,0,95,111,115,117,4,0,0,0,111,112,101, + 110,117,6,0,0,0,79,95,69,88,67,76,117,7,0,0, + 0,79,95,67,82,69,65,84,117,8,0,0,0,79,95,87, + 82,79,78,76,89,117,3,0,0,0,95,105,111,117,6,0, + 0,0,70,105,108,101,73,79,117,5,0,0,0,119,114,105, + 116,101,117,7,0,0,0,114,101,112,108,97,99,101,117,7, + 0,0,0,79,83,69,114,114,111,114,117,6,0,0,0,117, + 110,108,105,110,107,40,5,0,0,0,117,4,0,0,0,112, + 97,116,104,117,4,0,0,0,100,97,116,97,117,8,0,0, + 0,112,97,116,104,95,116,109,112,117,2,0,0,0,102,100, + 117,4,0,0,0,102,105,108,101,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,13,0,0,0,95,119,114,105,116,101, + 95,97,116,111,109,105,99,130,0,0,0,115,24,0,0,0, + 0,5,24,1,38,1,3,3,21,1,19,1,20,1,13,1, + 3,1,17,1,13,1,5,1,117,13,0,0,0,95,119,114, + 105,116,101,95,97,116,111,109,105,99,99,2,0,0,0,0, + 0,0,0,3,0,0,0,7,0,0,0,67,0,0,0,115, + 95,0,0,0,120,69,0,100,1,0,100,2,0,100,3,0, + 100,4,0,103,4,0,68,93,49,0,125,2,0,116,0,0, + 124,1,0,124,2,0,131,2,0,114,19,0,116,1,0,124, + 0,0,124,2,0,116,2,0,124,1,0,124,2,0,131,2, + 0,131,3,0,1,113,19,0,113,19,0,87,124,0,0,106, + 3,0,106,4,0,124,1,0,106,3,0,131,1,0,1,100, + 5,0,83,40,6,0,0,0,117,38,0,0,0,83,105,109, + 112,108,101,32,115,117,98,115,116,105,116,117,116,101,32,102, + 111,114,32,102,117,110,99,116,111,111,108,115,46,119,114,97, + 112,115,46,117,10,0,0,0,95,95,109,111,100,117,108,101, + 95,95,117,8,0,0,0,95,95,110,97,109,101,95,95,117, + 12,0,0,0,95,95,113,117,97,108,110,97,109,101,95,95, + 117,7,0,0,0,95,95,100,111,99,95,95,78,40,5,0, + 0,0,117,7,0,0,0,104,97,115,97,116,116,114,117,7, + 0,0,0,115,101,116,97,116,116,114,117,7,0,0,0,103, + 101,116,97,116,116,114,117,8,0,0,0,95,95,100,105,99, + 116,95,95,117,6,0,0,0,117,112,100,97,116,101,40,3, + 0,0,0,117,3,0,0,0,110,101,119,117,3,0,0,0, + 111,108,100,117,7,0,0,0,114,101,112,108,97,99,101,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,5,0,0,0, + 95,119,114,97,112,151,0,0,0,115,8,0,0,0,0,2, + 25,1,15,1,32,1,117,5,0,0,0,95,119,114,97,112, + 99,1,0,0,0,0,0,0,0,2,0,0,0,5,0,0, + 0,71,0,0,0,115,92,0,0,0,116,0,0,106,1,0, + 106,2,0,114,88,0,124,0,0,106,3,0,100,1,0,131, + 1,0,12,114,57,0,124,0,0,106,3,0,100,2,0,131, + 1,0,12,114,57,0,100,3,0,124,0,0,23,125,0,0, + 110,0,0,116,4,0,124,0,0,106,5,0,124,1,0,140, + 0,0,100,4,0,116,0,0,106,6,0,131,1,1,1,110, + 0,0,100,5,0,83,40,6,0,0,0,117,61,0,0,0, + 80,114,105,110,116,32,116,104,101,32,109,101,115,115,97,103, + 101,32,116,111,32,115,116,100,101,114,114,32,105,102,32,45, + 118,47,80,89,84,72,79,78,86,69,82,66,79,83,69,32, + 105,115,32,116,117,114,110,101,100,32,111,110,46,117,1,0, + 0,0,35,117,7,0,0,0,105,109,112,111,114,116,32,117, + 2,0,0,0,35,32,117,4,0,0,0,102,105,108,101,78, + 40,7,0,0,0,117,3,0,0,0,115,121,115,117,5,0, + 0,0,102,108,97,103,115,117,7,0,0,0,118,101,114,98, + 111,115,101,117,10,0,0,0,115,116,97,114,116,115,119,105, + 116,104,117,5,0,0,0,112,114,105,110,116,117,6,0,0, + 0,102,111,114,109,97,116,117,6,0,0,0,115,116,100,101, + 114,114,40,2,0,0,0,117,7,0,0,0,109,101,115,115, + 97,103,101,117,4,0,0,0,97,114,103,115,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,15,0,0,0,118,101,114, + 98,111,115,101,95,109,101,115,115,97,103,101,163,0,0,0, + 115,8,0,0,0,0,2,12,1,32,1,13,1,117,15,0, + 0,0,118,101,114,98,111,115,101,95,109,101,115,115,97,103, + 101,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,3,0,0,0,115,35,0,0,0,135,0,0,102,1, + 0,100,1,0,100,2,0,134,0,0,125,1,0,116,0,0, + 124,1,0,136,0,0,131,2,0,1,124,1,0,83,40,3, + 0,0,0,117,39,0,0,0,83,101,116,32,95,95,112,97, + 99,107,97,103,101,95,95,32,111,110,32,116,104,101,32,114, + 101,116,117,114,110,101,100,32,109,111,100,117,108,101,46,99, + 0,0,0,0,0,0,0,0,3,0,0,0,4,0,0,0, + 31,0,0,0,115,108,0,0,0,136,0,0,124,0,0,124, + 1,0,142,0,0,125,2,0,116,0,0,124,2,0,100,1, + 0,131,2,0,12,115,46,0,124,2,0,106,1,0,100,0, + 0,107,8,0,114,104,0,124,2,0,106,3,0,124,2,0, + 95,1,0,116,0,0,124,2,0,100,2,0,131,2,0,115, + 104,0,124,2,0,106,1,0,106,4,0,100,3,0,131,1, + 0,100,4,0,25,124,2,0,95,1,0,113,104,0,110,0, + 0,124,2,0,83,40,5,0,0,0,78,117,11,0,0,0, + 95,95,112,97,99,107,97,103,101,95,95,117,8,0,0,0, + 95,95,112,97,116,104,95,95,117,1,0,0,0,46,105,0, + 0,0,0,40,5,0,0,0,117,7,0,0,0,104,97,115, + 97,116,116,114,117,11,0,0,0,95,95,112,97,99,107,97, + 103,101,95,95,117,4,0,0,0,78,111,110,101,117,8,0, + 0,0,95,95,110,97,109,101,95,95,117,10,0,0,0,114, + 112,97,114,116,105,116,105,111,110,40,3,0,0,0,117,4, + 0,0,0,97,114,103,115,117,6,0,0,0,107,119,97,114, + 103,115,117,6,0,0,0,109,111,100,117,108,101,40,1,0, + 0,0,117,3,0,0,0,102,120,110,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,19,0,0,0,115,101,116,95,112,97,99,107,97,103, + 101,95,119,114,97,112,112,101,114,173,0,0,0,115,12,0, + 0,0,0,1,15,1,31,1,12,1,15,1,31,1,117,40, + 0,0,0,115,101,116,95,112,97,99,107,97,103,101,46,60, + 108,111,99,97,108,115,62,46,115,101,116,95,112,97,99,107, + 97,103,101,95,119,114,97,112,112,101,114,40,1,0,0,0, + 117,5,0,0,0,95,119,114,97,112,40,2,0,0,0,117, + 3,0,0,0,102,120,110,117,19,0,0,0,115,101,116,95, + 112,97,99,107,97,103,101,95,119,114,97,112,112,101,114,40, + 0,0,0,0,40,1,0,0,0,117,3,0,0,0,102,120, + 110,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,11,0,0,0,115,101,116,95,112,97,99,107, + 97,103,101,171,0,0,0,115,6,0,0,0,0,2,18,7, + 13,1,117,11,0,0,0,115,101,116,95,112,97,99,107,97, + 103,101,99,1,0,0,0,0,0,0,0,2,0,0,0,3, + 0,0,0,3,0,0,0,115,35,0,0,0,135,0,0,102, + 1,0,100,1,0,100,2,0,134,0,0,125,1,0,116,0, + 0,124,1,0,136,0,0,131,2,0,1,124,1,0,83,40, + 3,0,0,0,117,38,0,0,0,83,101,116,32,95,95,108, + 111,97,100,101,114,95,95,32,111,110,32,116,104,101,32,114, + 101,116,117,114,110,101,100,32,109,111,100,117,108,101,46,99, + 1,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, + 31,0,0,0,115,49,0,0,0,136,0,0,124,0,0,124, + 1,0,124,2,0,142,1,0,125,3,0,116,0,0,124,3, + 0,100,1,0,131,2,0,115,45,0,124,0,0,124,3,0, + 95,1,0,110,0,0,124,3,0,83,40,2,0,0,0,78, + 117,10,0,0,0,95,95,108,111,97,100,101,114,95,95,40, + 2,0,0,0,117,7,0,0,0,104,97,115,97,116,116,114, + 117,10,0,0,0,95,95,108,111,97,100,101,114,95,95,40, + 4,0,0,0,117,4,0,0,0,115,101,108,102,117,4,0, + 0,0,97,114,103,115,117,6,0,0,0,107,119,97,114,103, + 115,117,6,0,0,0,109,111,100,117,108,101,40,1,0,0, + 0,117,3,0,0,0,102,120,110,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,18,0,0,0,115,101,116,95,108,111,97,100,101,114,95, + 119,114,97,112,112,101,114,186,0,0,0,115,8,0,0,0, + 0,1,18,1,15,1,12,1,117,38,0,0,0,115,101,116, + 95,108,111,97,100,101,114,46,60,108,111,99,97,108,115,62, + 46,115,101,116,95,108,111,97,100,101,114,95,119,114,97,112, + 112,101,114,40,1,0,0,0,117,5,0,0,0,95,119,114, + 97,112,40,2,0,0,0,117,3,0,0,0,102,120,110,117, + 18,0,0,0,115,101,116,95,108,111,97,100,101,114,95,119, + 114,97,112,112,101,114,40,0,0,0,0,40,1,0,0,0, + 117,3,0,0,0,102,120,110,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,115, + 101,116,95,108,111,97,100,101,114,184,0,0,0,115,6,0, + 0,0,0,2,18,5,13,1,117,10,0,0,0,115,101,116, + 95,108,111,97,100,101,114,99,1,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,3,0,0,0,115,35,0,0, + 0,135,0,0,102,1,0,100,1,0,100,2,0,134,0,0, + 125,1,0,116,0,0,124,1,0,136,0,0,131,2,0,1, + 124,1,0,83,40,3,0,0,0,117,28,2,0,0,68,101, + 99,111,114,97,116,111,114,32,116,111,32,104,97,110,100,108, + 101,32,115,101,108,101,99,116,105,110,103,32,116,104,101,32, + 112,114,111,112,101,114,32,109,111,100,117,108,101,32,102,111, + 114,32,108,111,97,100,101,114,115,46,10,10,32,32,32,32, + 84,104,101,32,100,101,99,111,114,97,116,101,100,32,102,117, + 110,99,116,105,111,110,32,105,115,32,112,97,115,115,101,100, + 32,116,104,101,32,109,111,100,117,108,101,32,116,111,32,117, + 115,101,32,105,110,115,116,101,97,100,32,111,102,32,116,104, + 101,32,109,111,100,117,108,101,10,32,32,32,32,110,97,109, + 101,46,32,84,104,101,32,109,111,100,117,108,101,32,112,97, + 115,115,101,100,32,105,110,32,116,111,32,116,104,101,32,102, + 117,110,99,116,105,111,110,32,105,115,32,101,105,116,104,101, + 114,32,102,114,111,109,32,115,121,115,46,109,111,100,117,108, + 101,115,32,105,102,10,32,32,32,32,105,116,32,97,108,114, + 101,97,100,121,32,101,120,105,115,116,115,32,111,114,32,105, + 115,32,97,32,110,101,119,32,109,111,100,117,108,101,32,119, + 104,105,99,104,32,104,97,115,32,95,95,110,97,109,101,95, + 95,32,115,101,116,32,97,110,100,32,105,115,32,105,110,115, + 101,114,116,101,100,10,32,32,32,32,105,110,116,111,32,115, + 121,115,46,109,111,100,117,108,101,115,46,32,73,102,32,97, + 110,32,101,120,99,101,112,116,105,111,110,32,105,115,32,114, + 97,105,115,101,100,32,97,110,100,32,116,104,101,32,100,101, + 99,111,114,97,116,111,114,32,99,114,101,97,116,101,100,32, + 116,104,101,10,32,32,32,32,109,111,100,117,108,101,32,105, + 116,32,105,115,32,115,117,98,115,101,113,117,101,110,116,108, + 121,32,114,101,109,111,118,101,100,32,102,114,111,109,32,115, + 121,115,46,109,111,100,117,108,101,115,46,10,10,32,32,32, + 32,84,104,101,32,100,101,99,111,114,97,116,111,114,32,97, + 115,115,117,109,101,115,32,116,104,97,116,32,116,104,101,32, + 100,101,99,111,114,97,116,101,100,32,102,117,110,99,116,105, + 111,110,32,116,97,107,101,115,32,116,104,101,32,109,111,100, + 117,108,101,32,110,97,109,101,32,97,115,10,32,32,32,32, + 116,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109, + 101,110,116,46,10,10,32,32,32,32,99,2,0,0,0,0, + 0,0,0,6,0,0,0,11,0,0,0,31,0,0,0,115, + 127,0,0,0,116,0,0,106,1,0,106,2,0,124,1,0, + 131,1,0,125,4,0,116,3,0,124,4,0,131,1,0,125, + 5,0,124,5,0,115,67,0,116,4,0,106,5,0,124,1, + 0,131,1,0,125,4,0,124,4,0,116,0,0,106,1,0, + 124,1,0,60,110,0,0,121,23,0,136,0,0,124,0,0, + 124,4,0,124,2,0,124,3,0,142,2,0,83,87,110,30, + 0,1,1,1,124,5,0,115,115,0,116,0,0,106,1,0, + 124,1,0,61,110,0,0,130,0,0,89,110,1,0,88,100, + 0,0,83,40,1,0,0,0,78,40,6,0,0,0,117,3, + 0,0,0,115,121,115,117,7,0,0,0,109,111,100,117,108, + 101,115,117,3,0,0,0,103,101,116,117,4,0,0,0,98, + 111,111,108,117,3,0,0,0,105,109,112,117,10,0,0,0, + 110,101,119,95,109,111,100,117,108,101,40,6,0,0,0,117, + 4,0,0,0,115,101,108,102,117,8,0,0,0,102,117,108, + 108,110,97,109,101,117,4,0,0,0,97,114,103,115,117,6, + 0,0,0,107,119,97,114,103,115,117,6,0,0,0,109,111, + 100,117,108,101,117,9,0,0,0,105,115,95,114,101,108,111, + 97,100,40,1,0,0,0,117,3,0,0,0,102,120,110,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,25,0,0,0,109,111,100,117,108, + 101,95,102,111,114,95,108,111,97,100,101,114,95,119,114,97, + 112,112,101,114,208,0,0,0,115,22,0,0,0,0,1,18, + 1,12,1,6,4,15,1,16,1,3,1,23,1,3,1,6, + 1,13,1,117,52,0,0,0,109,111,100,117,108,101,95,102, + 111,114,95,108,111,97,100,101,114,46,60,108,111,99,97,108, + 115,62,46,109,111,100,117,108,101,95,102,111,114,95,108,111, + 97,100,101,114,95,119,114,97,112,112,101,114,40,1,0,0, + 0,117,5,0,0,0,95,119,114,97,112,40,2,0,0,0, + 117,3,0,0,0,102,120,110,117,25,0,0,0,109,111,100, + 117,108,101,95,102,111,114,95,108,111,97,100,101,114,95,119, + 114,97,112,112,101,114,40,0,0,0,0,40,1,0,0,0, + 117,3,0,0,0,102,120,110,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,17,0,0,0,109, + 111,100,117,108,101,95,102,111,114,95,108,111,97,100,101,114, + 195,0,0,0,115,6,0,0,0,0,13,18,15,13,1,117, + 17,0,0,0,109,111,100,117,108,101,95,102,111,114,95,108, + 111,97,100,101,114,99,1,0,0,0,0,0,0,0,2,0, + 0,0,3,0,0,0,3,0,0,0,115,35,0,0,0,135, + 0,0,102,1,0,100,1,0,100,2,0,134,0,0,125,1, + 0,116,0,0,124,1,0,136,0,0,131,2,0,1,124,1, + 0,83,40,3,0,0,0,117,252,0,0,0,68,101,99,111, + 114,97,116,111,114,32,116,111,32,118,101,114,105,102,121,32, + 116,104,97,116,32,116,104,101,32,109,111,100,117,108,101,32, + 98,101,105,110,103,32,114,101,113,117,101,115,116,101,100,32, + 109,97,116,99,104,101,115,32,116,104,101,32,111,110,101,32, + 116,104,101,10,32,32,32,32,108,111,97,100,101,114,32,99, + 97,110,32,104,97,110,100,108,101,46,10,10,32,32,32,32, + 84,104,101,32,102,105,114,115,116,32,97,114,103,117,109,101, + 110,116,32,40,115,101,108,102,41,32,109,117,115,116,32,100, + 101,102,105,110,101,32,95,110,97,109,101,32,119,104,105,99, + 104,32,116,104,101,32,115,101,99,111,110,100,32,97,114,103, + 117,109,101,110,116,32,105,115,10,32,32,32,32,99,111,109, + 112,97,114,101,100,32,97,103,97,105,110,115,116,46,32,73, + 102,32,116,104,101,32,99,111,109,112,97,114,105,115,111,110, + 32,102,97,105,108,115,32,116,104,101,110,32,73,109,112,111, + 114,116,69,114,114,111,114,32,105,115,32,114,97,105,115,101, + 100,46,10,10,32,32,32,32,99,2,0,0,0,0,0,0, + 0,4,0,0,0,5,0,0,0,31,0,0,0,115,59,0, + 0,0,124,0,0,106,0,0,124,1,0,107,3,0,114,40, + 0,116,1,0,100,1,0,124,1,0,22,100,2,0,124,1, + 0,131,1,1,130,1,0,110,0,0,136,0,0,124,0,0, + 124,1,0,124,2,0,124,3,0,142,2,0,83,40,3,0, + 0,0,78,117,23,0,0,0,108,111,97,100,101,114,32,99, + 97,110,110,111,116,32,104,97,110,100,108,101,32,37,115,117, + 4,0,0,0,110,97,109,101,40,2,0,0,0,117,5,0, + 0,0,95,110,97,109,101,117,11,0,0,0,73,109,112,111, + 114,116,69,114,114,111,114,40,4,0,0,0,117,4,0,0, + 0,115,101,108,102,117,4,0,0,0,110,97,109,101,117,4, + 0,0,0,97,114,103,115,117,6,0,0,0,107,119,97,114, + 103,115,40,1,0,0,0,117,6,0,0,0,109,101,116,104, + 111,100,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,19,0,0,0,95,99, + 104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,101, + 114,235,0,0,0,115,6,0,0,0,0,1,15,1,25,1, + 117,40,0,0,0,95,99,104,101,99,107,95,110,97,109,101, + 46,60,108,111,99,97,108,115,62,46,95,99,104,101,99,107, + 95,110,97,109,101,95,119,114,97,112,112,101,114,40,1,0, + 0,0,117,5,0,0,0,95,119,114,97,112,40,2,0,0, + 0,117,6,0,0,0,109,101,116,104,111,100,117,19,0,0, + 0,95,99,104,101,99,107,95,110,97,109,101,95,119,114,97, + 112,112,101,114,40,0,0,0,0,40,1,0,0,0,117,6, + 0,0,0,109,101,116,104,111,100,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, + 95,99,104,101,99,107,95,110,97,109,101,227,0,0,0,115, + 6,0,0,0,0,8,18,4,13,1,117,11,0,0,0,95, + 99,104,101,99,107,95,110,97,109,101,99,1,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,115, + 35,0,0,0,135,0,0,102,1,0,100,1,0,100,2,0, + 134,0,0,125,1,0,116,0,0,124,1,0,136,0,0,131, + 2,0,1,124,1,0,83,40,3,0,0,0,117,49,0,0, + 0,68,101,99,111,114,97,116,111,114,32,116,111,32,118,101, + 114,105,102,121,32,116,104,101,32,110,97,109,101,100,32,109, + 111,100,117,108,101,32,105,115,32,98,117,105,108,116,45,105, + 110,46,99,2,0,0,0,0,0,0,0,2,0,0,0,4, + 0,0,0,19,0,0,0,115,58,0,0,0,124,1,0,116, + 0,0,106,1,0,107,7,0,114,45,0,116,2,0,100,1, + 0,106,3,0,124,1,0,131,1,0,100,2,0,124,1,0, + 131,1,1,130,1,0,110,0,0,136,0,0,124,0,0,124, + 1,0,131,2,0,83,40,3,0,0,0,78,117,28,0,0, + 0,123,48,125,32,105,115,32,110,111,116,32,97,32,98,117, + 105,108,116,45,105,110,32,109,111,100,117,108,101,117,4,0, + 0,0,110,97,109,101,40,4,0,0,0,117,3,0,0,0, + 115,121,115,117,20,0,0,0,98,117,105,108,116,105,110,95, + 109,111,100,117,108,101,95,110,97,109,101,115,117,11,0,0, + 0,73,109,112,111,114,116,69,114,114,111,114,117,6,0,0, + 0,102,111,114,109,97,116,40,2,0,0,0,117,4,0,0, + 0,115,101,108,102,117,8,0,0,0,102,117,108,108,110,97, + 109,101,40,1,0,0,0,117,3,0,0,0,102,120,110,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,25,0,0,0,95,114,101,113,117, + 105,114,101,115,95,98,117,105,108,116,105,110,95,119,114,97, + 112,112,101,114,245,0,0,0,115,8,0,0,0,0,1,15, + 1,18,1,12,1,117,52,0,0,0,95,114,101,113,117,105, + 114,101,115,95,98,117,105,108,116,105,110,46,60,108,111,99, + 97,108,115,62,46,95,114,101,113,117,105,114,101,115,95,98, + 117,105,108,116,105,110,95,119,114,97,112,112,101,114,40,1, + 0,0,0,117,5,0,0,0,95,119,114,97,112,40,2,0, + 0,0,117,3,0,0,0,102,120,110,117,25,0,0,0,95, + 114,101,113,117,105,114,101,115,95,98,117,105,108,116,105,110, + 95,119,114,97,112,112,101,114,40,0,0,0,0,40,1,0, + 0,0,117,3,0,0,0,102,120,110,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,17,0,0, + 0,95,114,101,113,117,105,114,101,115,95,98,117,105,108,116, + 105,110,243,0,0,0,115,6,0,0,0,0,2,18,5,13, + 1,117,17,0,0,0,95,114,101,113,117,105,114,101,115,95, + 98,117,105,108,116,105,110,99,1,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,3,0,0,0,115,35,0,0, + 0,135,0,0,102,1,0,100,1,0,100,2,0,134,0,0, + 125,1,0,116,0,0,124,1,0,136,0,0,131,2,0,1, + 124,1,0,83,40,3,0,0,0,117,47,0,0,0,68,101, + 99,111,114,97,116,111,114,32,116,111,32,118,101,114,105,102, + 121,32,116,104,101,32,110,97,109,101,100,32,109,111,100,117, + 108,101,32,105,115,32,102,114,111,122,101,110,46,99,2,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,19,0, + 0,0,115,58,0,0,0,116,0,0,106,1,0,124,1,0, + 131,1,0,115,45,0,116,2,0,100,1,0,106,3,0,124, + 1,0,131,1,0,100,2,0,124,1,0,131,1,1,130,1, + 0,110,0,0,136,0,0,124,0,0,124,1,0,131,2,0, + 83,40,3,0,0,0,78,117,26,0,0,0,123,48,125,32, + 105,115,32,110,111,116,32,97,32,102,114,111,122,101,110,32, + 109,111,100,117,108,101,117,4,0,0,0,110,97,109,101,40, + 4,0,0,0,117,3,0,0,0,105,109,112,117,9,0,0, + 0,105,115,95,102,114,111,122,101,110,117,11,0,0,0,73, + 109,112,111,114,116,69,114,114,111,114,117,6,0,0,0,102, + 111,114,109,97,116,40,2,0,0,0,117,4,0,0,0,115, + 101,108,102,117,8,0,0,0,102,117,108,108,110,97,109,101, + 40,1,0,0,0,117,3,0,0,0,102,120,110,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,24,0,0,0,95,114,101,113,117,105,114, + 101,115,95,102,114,111,122,101,110,95,119,114,97,112,112,101, + 114,0,1,0,0,115,8,0,0,0,0,1,15,1,18,1, + 12,1,117,50,0,0,0,95,114,101,113,117,105,114,101,115, + 95,102,114,111,122,101,110,46,60,108,111,99,97,108,115,62, + 46,95,114,101,113,117,105,114,101,115,95,102,114,111,122,101, + 110,95,119,114,97,112,112,101,114,40,1,0,0,0,117,5, + 0,0,0,95,119,114,97,112,40,2,0,0,0,117,3,0, + 0,0,102,120,110,117,24,0,0,0,95,114,101,113,117,105, + 114,101,115,95,102,114,111,122,101,110,95,119,114,97,112,112, + 101,114,40,0,0,0,0,40,1,0,0,0,117,3,0,0, + 0,102,120,110,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,16,0,0,0,95,114,101,113,117, + 105,114,101,115,95,102,114,111,122,101,110,254,0,0,0,115, + 6,0,0,0,0,2,18,5,13,1,117,16,0,0,0,95, + 114,101,113,117,105,114,101,115,95,102,114,111,122,101,110,99, + 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 3,0,0,0,115,29,0,0,0,135,0,0,102,1,0,100, + 1,0,100,2,0,134,0,0,116,0,0,106,1,0,131,0, + 0,68,131,1,0,83,40,3,0,0,0,117,58,0,0,0, + 82,101,116,117,114,110,32,97,32,108,105,115,116,32,111,102, + 32,102,105,108,101,32,115,117,102,102,105,120,101,115,32,98, + 97,115,101,100,32,111,110,32,116,104,101,32,105,109,112,32, + 102,105,108,101,32,116,121,112,101,46,99,1,0,0,0,0, + 0,0,0,2,0,0,0,4,0,0,0,19,0,0,0,115, + 42,0,0,0,103,0,0,124,0,0,93,32,0,125,1,0, + 124,1,0,100,0,0,25,136,0,0,107,2,0,114,6,0, + 124,1,0,100,1,0,25,145,2,0,113,6,0,83,40,2, + 0,0,0,105,2,0,0,0,105,0,0,0,0,40,0,0, + 0,0,40,2,0,0,0,117,2,0,0,0,46,48,117,6, + 0,0,0,115,117,102,102,105,120,40,1,0,0,0,117,11, + 0,0,0,115,117,102,102,105,120,95,116,121,112,101,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,10,0,0,0,60,108,105,115,116,99, + 111,109,112,62,11,1,0,0,115,4,0,0,0,9,0,3, + 1,117,32,0,0,0,95,115,117,102,102,105,120,95,108,105, + 115,116,46,60,108,111,99,97,108,115,62,46,60,108,105,115, + 116,99,111,109,112,62,40,2,0,0,0,117,3,0,0,0, + 105,109,112,117,12,0,0,0,103,101,116,95,115,117,102,102, + 105,120,101,115,40,1,0,0,0,117,11,0,0,0,115,117, + 102,102,105,120,95,116,121,112,101,40,0,0,0,0,40,1, + 0,0,0,117,11,0,0,0,115,117,102,102,105,120,95,116, + 121,112,101,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,12,0,0,0,95,115,117,102,102,105, + 120,95,108,105,115,116,9,1,0,0,115,2,0,0,0,0, + 2,117,12,0,0,0,95,115,117,102,102,105,120,95,108,105, + 115,116,99,1,0,0,0,0,0,0,0,1,0,0,0,6, + 0,0,0,66,0,0,0,115,155,0,0,0,124,0,0,69, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, + 3,0,101,4,0,100,12,0,100,2,0,100,3,0,132,1, + 0,131,1,0,90,6,0,101,4,0,101,7,0,101,8,0, + 101,9,0,100,4,0,100,5,0,132,0,0,131,1,0,131, + 1,0,131,1,0,131,1,0,90,10,0,101,4,0,101,9, + 0,100,6,0,100,7,0,132,0,0,131,1,0,131,1,0, + 90,11,0,101,4,0,101,9,0,100,8,0,100,9,0,132, + 0,0,131,1,0,131,1,0,90,12,0,101,4,0,101,9, + 0,100,10,0,100,11,0,132,0,0,131,1,0,131,1,0, + 90,13,0,100,12,0,83,40,13,0,0,0,117,15,0,0, + 0,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, + 117,144,0,0,0,77,101,116,97,32,112,97,116,104,32,105, + 109,112,111,114,116,32,102,111,114,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,115,46,10,10,32,32,32, + 32,65,108,108,32,109,101,116,104,111,100,115,32,97,114,101, + 32,101,105,116,104,101,114,32,99,108,97,115,115,32,111,114, + 32,115,116,97,116,105,99,32,109,101,116,104,111,100,115,32, + 116,111,32,97,118,111,105,100,32,116,104,101,32,110,101,101, + 100,32,116,111,10,32,32,32,32,105,110,115,116,97,110,116, + 105,97,116,101,32,116,104,101,32,99,108,97,115,115,46,10, + 10,32,32,32,32,99,3,0,0,0,0,0,0,0,3,0, + 0,0,2,0,0,0,67,0,0,0,115,39,0,0,0,124, + 2,0,100,1,0,107,9,0,114,16,0,100,1,0,83,116, + 1,0,106,2,0,124,1,0,131,1,0,114,35,0,124,0, + 0,83,100,1,0,83,40,2,0,0,0,117,113,0,0,0, + 70,105,110,100,32,116,104,101,32,98,117,105,108,116,45,105, + 110,32,109,111,100,117,108,101,46,10,10,32,32,32,32,32, + 32,32,32,73,102,32,39,112,97,116,104,39,32,105,115,32, + 101,118,101,114,32,115,112,101,99,105,102,105,101,100,32,116, + 104,101,110,32,116,104,101,32,115,101,97,114,99,104,32,105, + 115,32,99,111,110,115,105,100,101,114,101,100,32,97,32,102, + 97,105,108,117,114,101,46,10,10,32,32,32,32,32,32,32, + 32,78,40,3,0,0,0,117,4,0,0,0,78,111,110,101, + 117,3,0,0,0,105,109,112,117,10,0,0,0,105,115,95, + 98,117,105,108,116,105,110,40,3,0,0,0,117,3,0,0, + 0,99,108,115,117,8,0,0,0,102,117,108,108,110,97,109, + 101,117,4,0,0,0,112,97,116,104,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,11,0,0,0,102,105,110,100,95, + 109,111,100,117,108,101,26,1,0,0,115,6,0,0,0,0, + 7,12,1,4,1,117,27,0,0,0,66,117,105,108,116,105, + 110,73,109,112,111,114,116,101,114,46,102,105,110,100,95,109, + 111,100,117,108,101,99,2,0,0,0,0,0,0,0,3,0, + 0,0,9,0,0,0,67,0,0,0,115,85,0,0,0,124, + 1,0,116,0,0,106,1,0,107,6,0,125,2,0,121,17, + 0,116,2,0,106,3,0,124,1,0,131,1,0,83,87,110, + 46,0,1,1,1,124,2,0,12,114,73,0,124,1,0,116, + 0,0,106,1,0,107,6,0,114,73,0,116,0,0,106,1, + 0,124,1,0,61,110,0,0,130,0,0,89,110,1,0,88, + 100,1,0,83,40,2,0,0,0,117,23,0,0,0,76,111, + 97,100,32,97,32,98,117,105,108,116,45,105,110,32,109,111, + 100,117,108,101,46,78,40,4,0,0,0,117,3,0,0,0, + 115,121,115,117,7,0,0,0,109,111,100,117,108,101,115,117, + 3,0,0,0,105,109,112,117,12,0,0,0,105,110,105,116, + 95,98,117,105,108,116,105,110,40,3,0,0,0,117,3,0, + 0,0,99,108,115,117,8,0,0,0,102,117,108,108,110,97, + 109,101,117,9,0,0,0,105,115,95,114,101,108,111,97,100, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,11,0,0, + 0,108,111,97,100,95,109,111,100,117,108,101,37,1,0,0, + 115,14,0,0,0,0,6,15,1,3,1,17,1,3,1,22, + 1,13,1,117,27,0,0,0,66,117,105,108,116,105,110,73, + 109,112,111,114,116,101,114,46,108,111,97,100,95,109,111,100, + 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,0, + 83,40,2,0,0,0,117,57,0,0,0,82,101,116,117,114, + 110,32,78,111,110,101,32,97,115,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,115,32,100,111,32,110,111, + 116,32,104,97,118,101,32,99,111,100,101,32,111,98,106,101, + 99,116,115,46,78,40,1,0,0,0,117,4,0,0,0,78, + 111,110,101,40,2,0,0,0,117,3,0,0,0,99,108,115, + 117,8,0,0,0,102,117,108,108,110,97,109,101,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,8,0,0,0,103,101, + 116,95,99,111,100,101,51,1,0,0,115,2,0,0,0,0, + 4,117,24,0,0,0,66,117,105,108,116,105,110,73,109,112, + 111,114,116,101,114,46,103,101,116,95,99,111,100,101,99,2, + 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, + 0,0,0,115,4,0,0,0,100,1,0,83,40,2,0,0, + 0,117,56,0,0,0,82,101,116,117,114,110,32,78,111,110, + 101,32,97,115,32,98,117,105,108,116,45,105,110,32,109,111, + 100,117,108,101,115,32,100,111,32,110,111,116,32,104,97,118, + 101,32,115,111,117,114,99,101,32,99,111,100,101,46,78,40, + 1,0,0,0,117,4,0,0,0,78,111,110,101,40,2,0, + 0,0,117,3,0,0,0,99,108,115,117,8,0,0,0,102, + 117,108,108,110,97,109,101,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,10,0,0,0,103,101,116,95,115,111,117,114, + 99,101,57,1,0,0,115,2,0,0,0,0,4,117,26,0, + 0,0,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 114,46,103,101,116,95,115,111,117,114,99,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,0,83,40,2,0,0,0,117, + 51,0,0,0,82,101,116,117,114,110,32,78,111,110,101,32, + 97,115,32,98,117,105,108,116,45,105,110,32,109,111,100,117, + 108,101,115,32,97,114,101,32,110,101,118,101,114,32,112,97, + 99,107,97,103,101,115,46,70,40,1,0,0,0,117,5,0, + 0,0,70,97,108,115,101,40,2,0,0,0,117,3,0,0, + 0,99,108,115,117,8,0,0,0,102,117,108,108,110,97,109, + 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,10,0, + 0,0,105,115,95,112,97,99,107,97,103,101,63,1,0,0, + 115,2,0,0,0,0,4,117,26,0,0,0,66,117,105,108, + 116,105,110,73,109,112,111,114,116,101,114,46,105,115,95,112, + 97,99,107,97,103,101,78,40,14,0,0,0,117,8,0,0, + 0,95,95,110,97,109,101,95,95,117,10,0,0,0,95,95, + 109,111,100,117,108,101,95,95,117,12,0,0,0,95,95,113, + 117,97,108,110,97,109,101,95,95,117,7,0,0,0,95,95, + 100,111,99,95,95,117,11,0,0,0,99,108,97,115,115,109, + 101,116,104,111,100,117,4,0,0,0,78,111,110,101,117,11, + 0,0,0,102,105,110,100,95,109,111,100,117,108,101,117,11, + 0,0,0,115,101,116,95,112,97,99,107,97,103,101,117,10, + 0,0,0,115,101,116,95,108,111,97,100,101,114,117,17,0, + 0,0,95,114,101,113,117,105,114,101,115,95,98,117,105,108, + 116,105,110,117,11,0,0,0,108,111,97,100,95,109,111,100, + 117,108,101,117,8,0,0,0,103,101,116,95,99,111,100,101, + 117,10,0,0,0,103,101,116,95,115,111,117,114,99,101,117, + 10,0,0,0,105,115,95,112,97,99,107,97,103,101,40,1, + 0,0,0,117,10,0,0,0,95,95,108,111,99,97,108,115, + 95,95,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,15, + 0,0,0,66,117,105,108,116,105,110,73,109,112,111,114,116, + 101,114,17,1,0,0,115,26,0,0,0,16,7,6,2,3, + 1,18,10,3,1,3,1,3,1,27,11,3,1,21,5,3, + 1,21,5,3,1,117,15,0,0,0,66,117,105,108,116,105, + 110,73,109,112,111,114,116,101,114,99,1,0,0,0,0,0, + 0,0,1,0,0,0,6,0,0,0,66,0,0,0,115,155, + 0,0,0,124,0,0,69,101,0,0,90,1,0,100,0,0, + 90,2,0,100,1,0,90,3,0,101,4,0,100,12,0,100, + 2,0,100,3,0,132,1,0,131,1,0,90,6,0,101,4, + 0,101,7,0,101,8,0,101,9,0,100,4,0,100,5,0, + 132,0,0,131,1,0,131,1,0,131,1,0,131,1,0,90, + 10,0,101,4,0,101,9,0,100,6,0,100,7,0,132,0, + 0,131,1,0,131,1,0,90,11,0,101,4,0,101,9,0, + 100,8,0,100,9,0,132,0,0,131,1,0,131,1,0,90, + 12,0,101,4,0,101,9,0,100,10,0,100,11,0,132,0, + 0,131,1,0,131,1,0,90,13,0,100,12,0,83,40,13, + 0,0,0,117,14,0,0,0,70,114,111,122,101,110,73,109, + 112,111,114,116,101,114,117,142,0,0,0,77,101,116,97,32, + 112,97,116,104,32,105,109,112,111,114,116,32,102,111,114,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,115,46,10, + 10,32,32,32,32,65,108,108,32,109,101,116,104,111,100,115, + 32,97,114,101,32,101,105,116,104,101,114,32,99,108,97,115, + 115,32,111,114,32,115,116,97,116,105,99,32,109,101,116,104, + 111,100,115,32,116,111,32,97,118,111,105,100,32,116,104,101, + 32,110,101,101,100,32,116,111,10,32,32,32,32,105,110,115, + 116,97,110,116,105,97,116,101,32,116,104,101,32,99,108,97, + 115,115,46,10,10,32,32,32,32,99,3,0,0,0,0,0, + 0,0,3,0,0,0,2,0,0,0,67,0,0,0,115,23, + 0,0,0,116,0,0,106,1,0,124,1,0,131,1,0,114, + 19,0,124,0,0,83,100,1,0,83,40,2,0,0,0,117, + 21,0,0,0,70,105,110,100,32,97,32,102,114,111,122,101, + 110,32,109,111,100,117,108,101,46,78,40,3,0,0,0,117, + 3,0,0,0,105,109,112,117,9,0,0,0,105,115,95,102, + 114,111,122,101,110,117,4,0,0,0,78,111,110,101,40,3, + 0,0,0,117,3,0,0,0,99,108,115,117,8,0,0,0, + 102,117,108,108,110,97,109,101,117,4,0,0,0,112,97,116, + 104,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,11,0, + 0,0,102,105,110,100,95,109,111,100,117,108,101,79,1,0, + 0,115,2,0,0,0,0,3,117,26,0,0,0,70,114,111, + 122,101,110,73,109,112,111,114,116,101,114,46,102,105,110,100, + 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, + 3,0,0,0,9,0,0,0,67,0,0,0,115,85,0,0, + 0,124,1,0,116,0,0,106,1,0,107,6,0,125,2,0, + 121,17,0,116,2,0,106,3,0,124,1,0,131,1,0,83, + 87,110,46,0,1,1,1,124,2,0,12,114,73,0,124,1, + 0,116,0,0,106,1,0,107,6,0,114,73,0,116,0,0, + 106,1,0,124,1,0,61,110,0,0,130,0,0,89,110,1, + 0,88,100,1,0,83,40,2,0,0,0,117,21,0,0,0, + 76,111,97,100,32,97,32,102,114,111,122,101,110,32,109,111, + 100,117,108,101,46,78,40,4,0,0,0,117,3,0,0,0, + 115,121,115,117,7,0,0,0,109,111,100,117,108,101,115,117, + 3,0,0,0,105,109,112,117,11,0,0,0,105,110,105,116, + 95,102,114,111,122,101,110,40,3,0,0,0,117,3,0,0, + 0,99,108,115,117,8,0,0,0,102,117,108,108,110,97,109, + 101,117,9,0,0,0,105,115,95,114,101,108,111,97,100,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, + 108,111,97,100,95,109,111,100,117,108,101,84,1,0,0,115, + 14,0,0,0,0,6,15,1,3,1,17,1,3,1,22,1, + 13,1,117,26,0,0,0,70,114,111,122,101,110,73,109,112, + 111,114,116,101,114,46,108,111,97,100,95,109,111,100,117,108, + 101,99,2,0,0,0,0,0,0,0,2,0,0,0,2,0, + 0,0,67,0,0,0,115,13,0,0,0,116,0,0,106,1, + 0,124,1,0,131,1,0,83,40,1,0,0,0,117,45,0, + 0,0,82,101,116,117,114,110,32,116,104,101,32,99,111,100, + 101,32,111,98,106,101,99,116,32,102,111,114,32,116,104,101, + 32,102,114,111,122,101,110,32,109,111,100,117,108,101,46,40, + 2,0,0,0,117,3,0,0,0,105,109,112,117,17,0,0, + 0,103,101,116,95,102,114,111,122,101,110,95,111,98,106,101, + 99,116,40,2,0,0,0,117,3,0,0,0,99,108,115,117, + 8,0,0,0,102,117,108,108,110,97,109,101,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,8,0,0,0,103,101,116, + 95,99,111,100,101,98,1,0,0,115,2,0,0,0,0,4, + 117,23,0,0,0,70,114,111,122,101,110,73,109,112,111,114, + 116,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,0,83,40,2,0,0,0,117, + 54,0,0,0,82,101,116,117,114,110,32,78,111,110,101,32, + 97,115,32,102,114,111,122,101,110,32,109,111,100,117,108,101, + 115,32,100,111,32,110,111,116,32,104,97,118,101,32,115,111, + 117,114,99,101,32,99,111,100,101,46,78,40,1,0,0,0, + 117,4,0,0,0,78,111,110,101,40,2,0,0,0,117,3, + 0,0,0,99,108,115,117,8,0,0,0,102,117,108,108,110, + 97,109,101,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 10,0,0,0,103,101,116,95,115,111,117,114,99,101,104,1, + 0,0,115,2,0,0,0,0,4,117,25,0,0,0,70,114, + 111,122,101,110,73,109,112,111,114,116,101,114,46,103,101,116, + 95,115,111,117,114,99,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,2,0,0,0,67,0,0,0,115,13,0,0, + 0,116,0,0,106,1,0,124,1,0,131,1,0,83,40,1, + 0,0,0,117,41,0,0,0,82,101,116,117,114,110,32,105, + 102,32,116,104,101,32,102,114,111,122,101,110,32,109,111,100, + 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, + 46,40,2,0,0,0,117,3,0,0,0,105,109,112,117,17, + 0,0,0,105,115,95,102,114,111,122,101,110,95,112,97,99, + 107,97,103,101,40,2,0,0,0,117,3,0,0,0,99,108, + 115,117,8,0,0,0,102,117,108,108,110,97,109,101,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,105, + 115,95,112,97,99,107,97,103,101,110,1,0,0,115,2,0, + 0,0,0,4,117,25,0,0,0,70,114,111,122,101,110,73, + 109,112,111,114,116,101,114,46,105,115,95,112,97,99,107,97, + 103,101,78,40,14,0,0,0,117,8,0,0,0,95,95,110, + 97,109,101,95,95,117,10,0,0,0,95,95,109,111,100,117, + 108,101,95,95,117,12,0,0,0,95,95,113,117,97,108,110, + 97,109,101,95,95,117,7,0,0,0,95,95,100,111,99,95, + 95,117,11,0,0,0,99,108,97,115,115,109,101,116,104,111, + 100,117,4,0,0,0,78,111,110,101,117,11,0,0,0,102, + 105,110,100,95,109,111,100,117,108,101,117,11,0,0,0,115, + 101,116,95,112,97,99,107,97,103,101,117,10,0,0,0,115, + 101,116,95,108,111,97,100,101,114,117,16,0,0,0,95,114, + 101,113,117,105,114,101,115,95,102,114,111,122,101,110,117,11, + 0,0,0,108,111,97,100,95,109,111,100,117,108,101,117,8, + 0,0,0,103,101,116,95,99,111,100,101,117,10,0,0,0, + 103,101,116,95,115,111,117,114,99,101,117,10,0,0,0,105, + 115,95,112,97,99,107,97,103,101,40,1,0,0,0,117,10, + 0,0,0,95,95,108,111,99,97,108,115,95,95,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,14,0,0,0,70,114, + 111,122,101,110,73,109,112,111,114,116,101,114,70,1,0,0, + 115,26,0,0,0,16,7,6,2,3,1,18,4,3,1,3, + 1,3,1,27,11,3,1,21,5,3,1,21,5,3,1,117, + 14,0,0,0,70,114,111,122,101,110,73,109,112,111,114,116, + 101,114,99,1,0,0,0,0,0,0,0,1,0,0,0,5, + 0,0,0,66,0,0,0,115,74,0,0,0,124,0,0,69, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, + 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, + 0,100,5,0,132,0,0,90,5,0,101,6,0,100,6,0, + 100,10,0,100,7,0,100,8,0,132,0,1,131,1,0,90, + 8,0,100,9,0,83,40,11,0,0,0,117,13,0,0,0, + 95,76,111,97,100,101,114,66,97,115,105,99,115,117,84,0, + 0,0,66,97,115,101,32,99,108,97,115,115,32,111,102,32, + 99,111,109,109,111,110,32,99,111,100,101,32,110,101,101,100, + 101,100,32,98,121,32,98,111,116,104,32,83,111,117,114,99, + 101,76,111,97,100,101,114,32,97,110,100,10,32,32,32,32, + 95,83,111,117,114,99,101,108,101,115,115,70,105,108,101,76, + 111,97,100,101,114,46,99,2,0,0,0,0,0,0,0,3, + 0,0,0,3,0,0,0,67,0,0,0,115,54,0,0,0, + 124,0,0,106,0,0,124,1,0,131,1,0,106,1,0,116, + 2,0,131,1,0,100,1,0,25,125,2,0,124,2,0,106, + 3,0,100,2,0,100,3,0,131,2,0,100,4,0,25,100, + 5,0,107,2,0,83,40,6,0,0,0,117,141,0,0,0, + 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, + 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, + 99,116,76,111,97,100,101,114,46,105,115,95,112,97,99,107, + 97,103,101,32,98,121,32,99,104,101,99,107,105,110,103,32, + 105,102,10,32,32,32,32,32,32,32,32,116,104,101,32,112, + 97,116,104,32,114,101,116,117,114,110,101,100,32,98,121,32, + 103,101,116,95,102,105,108,101,110,97,109,101,32,104,97,115, + 32,97,32,102,105,108,101,110,97,109,101,32,111,102,32,39, + 95,95,105,110,105,116,95,95,46,112,121,39,46,105,2,0, + 0,0,117,1,0,0,0,46,105,1,0,0,0,105,0,0, + 0,0,117,8,0,0,0,95,95,105,110,105,116,95,95,40, + 4,0,0,0,117,12,0,0,0,103,101,116,95,102,105,108, + 101,110,97,109,101,117,10,0,0,0,114,112,97,114,116,105, + 116,105,111,110,117,8,0,0,0,112,97,116,104,95,115,101, + 112,117,6,0,0,0,114,115,112,108,105,116,40,3,0,0, + 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,102, + 117,108,108,110,97,109,101,117,8,0,0,0,102,105,108,101, + 110,97,109,101,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,10,0,0,0,105,115,95,112,97,99,107,97,103,101,122, + 1,0,0,115,4,0,0,0,0,3,28,1,117,24,0,0, + 0,95,76,111,97,100,101,114,66,97,115,105,99,115,46,105, + 115,95,112,97,99,107,97,103,101,99,5,0,0,0,0,0, + 0,0,11,0,0,0,23,0,0,0,67,0,0,0,115,213, + 1,0,0,124,2,0,100,1,0,100,2,0,133,2,0,25, + 125,5,0,124,2,0,100,2,0,100,3,0,133,2,0,25, + 125,6,0,124,2,0,100,3,0,100,4,0,133,2,0,25, + 125,7,0,116,0,0,124,5,0,131,1,0,100,2,0,107, + 3,0,115,84,0,124,5,0,116,1,0,106,2,0,131,0, + 0,107,3,0,114,120,0,116,3,0,100,5,0,106,4,0, + 124,1,0,131,1,0,100,6,0,124,1,0,100,7,0,124, + 3,0,131,1,2,130,1,0,110,116,0,116,0,0,124,6, + 0,131,1,0,100,2,0,107,3,0,114,178,0,100,8,0, + 106,4,0,124,1,0,131,1,0,125,8,0,116,5,0,124, + 8,0,131,1,0,1,116,6,0,124,8,0,131,1,0,130, + 1,0,110,58,0,116,0,0,124,7,0,131,1,0,100,2, + 0,107,3,0,114,236,0,100,9,0,106,4,0,124,1,0, + 131,1,0,125,8,0,116,5,0,124,8,0,131,1,0,1, + 116,6,0,124,8,0,131,1,0,130,1,0,110,0,0,124, + 4,0,100,1,0,107,9,0,114,199,1,121,20,0,116,8, + 0,124,4,0,100,10,0,25,131,1,0,125,9,0,87,110, + 18,0,4,116,9,0,107,10,0,114,32,1,1,1,1,89, + 110,71,0,88,116,10,0,124,6,0,131,1,0,124,9,0, + 107,3,0,114,103,1,100,11,0,106,4,0,124,1,0,131, + 1,0,125,8,0,116,5,0,124,8,0,131,1,0,1,116, + 3,0,124,8,0,100,6,0,124,1,0,100,7,0,124,3, + 0,131,1,2,130,1,0,110,0,0,121,18,0,124,4,0, + 100,12,0,25,100,13,0,64,125,10,0,87,110,18,0,4, + 116,9,0,107,10,0,114,141,1,1,1,1,89,113,199,1, + 88,116,10,0,124,7,0,131,1,0,124,10,0,107,3,0, + 114,199,1,116,3,0,100,11,0,106,4,0,124,1,0,131, + 1,0,100,6,0,124,1,0,100,7,0,124,3,0,131,1, + 2,130,1,0,113,199,1,110,0,0,124,2,0,100,4,0, + 100,1,0,133,2,0,25,83,40,14,0,0,0,117,193,0, + 0,0,82,101,116,117,114,110,32,116,104,101,32,109,97,114, + 115,104,97,108,108,101,100,32,98,121,116,101,115,32,102,114, + 111,109,32,98,121,116,101,99,111,100,101,44,32,118,101,114, + 105,102,121,105,110,103,32,116,104,101,32,109,97,103,105,99, + 10,32,32,32,32,32,32,32,32,110,117,109,98,101,114,44, + 32,116,105,109,101,115,116,97,109,112,32,97,110,100,32,115, + 111,117,114,99,101,32,115,105,122,101,32,97,108,111,110,103, + 32,116,104,101,32,119,97,121,46,10,10,32,32,32,32,32, + 32,32,32,73,102,32,115,111,117,114,99,101,95,115,116,97, + 116,115,32,105,115,32,78,111,110,101,32,116,104,101,110,32, + 115,107,105,112,32,116,104,101,32,116,105,109,101,115,116,97, + 109,112,32,99,104,101,99,107,46,10,10,32,32,32,32,32, + 32,32,32,78,105,4,0,0,0,105,8,0,0,0,105,12, + 0,0,0,117,22,0,0,0,98,97,100,32,109,97,103,105, + 99,32,110,117,109,98,101,114,32,105,110,32,123,125,117,4, + 0,0,0,110,97,109,101,117,4,0,0,0,112,97,116,104, + 117,19,0,0,0,98,97,100,32,116,105,109,101,115,116,97, + 109,112,32,105,110,32,123,125,117,14,0,0,0,98,97,100, + 32,115,105,122,101,32,105,110,32,123,125,117,5,0,0,0, + 109,116,105,109,101,117,24,0,0,0,98,121,116,101,99,111, + 100,101,32,105,115,32,115,116,97,108,101,32,102,111,114,32, + 123,125,117,4,0,0,0,115,105,122,101,73,255,255,255,255, + 0,0,0,0,40,11,0,0,0,117,3,0,0,0,108,101, + 110,117,3,0,0,0,105,109,112,117,9,0,0,0,103,101, + 116,95,109,97,103,105,99,117,11,0,0,0,73,109,112,111, + 114,116,69,114,114,111,114,117,6,0,0,0,102,111,114,109, + 97,116,117,15,0,0,0,118,101,114,98,111,115,101,95,109, + 101,115,115,97,103,101,117,8,0,0,0,69,79,70,69,114, + 114,111,114,117,4,0,0,0,78,111,110,101,117,3,0,0, + 0,105,110,116,117,8,0,0,0,75,101,121,69,114,114,111, + 114,117,7,0,0,0,95,114,95,108,111,110,103,40,11,0, + 0,0,117,4,0,0,0,115,101,108,102,117,8,0,0,0, + 102,117,108,108,110,97,109,101,117,4,0,0,0,100,97,116, + 97,117,13,0,0,0,98,121,116,101,99,111,100,101,95,112, + 97,116,104,117,12,0,0,0,115,111,117,114,99,101,95,115, + 116,97,116,115,117,5,0,0,0,109,97,103,105,99,117,13, + 0,0,0,114,97,119,95,116,105,109,101,115,116,97,109,112, + 117,8,0,0,0,114,97,119,95,115,105,122,101,117,7,0, + 0,0,109,101,115,115,97,103,101,117,12,0,0,0,115,111, + 117,114,99,101,95,109,116,105,109,101,117,11,0,0,0,115, + 111,117,114,99,101,95,115,105,122,101,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,20,0,0,0,95,98,121,116,101, + 115,95,102,114,111,109,95,98,121,116,101,99,111,100,101,128, + 1,0,0,115,66,0,0,0,0,7,16,1,16,1,16,1, + 36,1,18,1,18,1,18,1,15,1,10,1,15,1,18,1, + 15,1,10,1,15,1,12,1,3,1,20,1,13,1,5,2, + 18,1,15,1,10,1,15,1,12,1,3,1,18,1,13,1, + 5,2,18,1,3,1,15,1,21,3,117,34,0,0,0,95, + 76,111,97,100,101,114,66,97,115,105,99,115,46,95,98,121, + 116,101,115,95,102,114,111,109,95,98,121,116,101,99,111,100, + 101,117,10,0,0,0,115,111,117,114,99,101,108,101,115,115, + 99,2,0,0,0,1,0,0,0,5,0,0,0,3,0,0, + 0,67,0,0,0,115,196,0,0,0,124,1,0,106,0,0, + 125,3,0,124,0,0,106,1,0,124,3,0,131,1,0,125, + 4,0,124,0,0,106,2,0,124,3,0,131,1,0,124,1, + 0,95,3,0,124,2,0,115,72,0,116,4,0,106,5,0, + 124,1,0,106,3,0,131,1,0,124,1,0,95,6,0,110, + 12,0,124,1,0,106,3,0,124,1,0,95,6,0,124,3, + 0,124,1,0,95,7,0,124,0,0,106,8,0,124,3,0, + 131,1,0,114,142,0,124,1,0,106,3,0,106,9,0,116, + 10,0,100,1,0,131,2,0,100,2,0,25,103,1,0,124, + 1,0,95,11,0,110,25,0,124,1,0,106,7,0,106,12, + 0,100,3,0,131,1,0,100,2,0,25,124,1,0,95,7, + 0,124,0,0,124,1,0,95,13,0,116,14,0,124,4,0, + 124,1,0,106,15,0,131,2,0,1,124,1,0,83,40,4, + 0,0,0,117,82,0,0,0,72,101,108,112,101,114,32,102, + 111,114,32,108,111,97,100,95,109,111,100,117,108,101,32,97, + 98,108,101,32,116,111,32,104,97,110,100,108,101,32,101,105, + 116,104,101,114,32,115,111,117,114,99,101,32,111,114,32,115, + 111,117,114,99,101,108,101,115,115,10,32,32,32,32,32,32, + 32,32,108,111,97,100,105,110,103,46,105,1,0,0,0,105, + 0,0,0,0,117,1,0,0,0,46,40,16,0,0,0,117, + 8,0,0,0,95,95,110,97,109,101,95,95,117,8,0,0, + 0,103,101,116,95,99,111,100,101,117,12,0,0,0,103,101, + 116,95,102,105,108,101,110,97,109,101,117,8,0,0,0,95, + 95,102,105,108,101,95,95,117,3,0,0,0,105,109,112,117, + 17,0,0,0,99,97,99,104,101,95,102,114,111,109,95,115, + 111,117,114,99,101,117,10,0,0,0,95,95,99,97,99,104, + 101,100,95,95,117,11,0,0,0,95,95,112,97,99,107,97, + 103,101,95,95,117,10,0,0,0,105,115,95,112,97,99,107, + 97,103,101,117,6,0,0,0,114,115,112,108,105,116,117,8, + 0,0,0,112,97,116,104,95,115,101,112,117,8,0,0,0, + 95,95,112,97,116,104,95,95,117,10,0,0,0,114,112,97, + 114,116,105,116,105,111,110,117,10,0,0,0,95,95,108,111, + 97,100,101,114,95,95,117,4,0,0,0,101,120,101,99,117, + 8,0,0,0,95,95,100,105,99,116,95,95,40,5,0,0, + 0,117,4,0,0,0,115,101,108,102,117,6,0,0,0,109, + 111,100,117,108,101,117,10,0,0,0,115,111,117,114,99,101, + 108,101,115,115,117,4,0,0,0,110,97,109,101,117,11,0, + 0,0,99,111,100,101,95,111,98,106,101,99,116,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,12,0,0,0,95,108, + 111,97,100,95,109,111,100,117,108,101,173,1,0,0,115,26, + 0,0,0,0,4,9,1,15,1,18,1,6,1,24,2,12, + 1,9,1,15,1,34,2,25,1,9,1,16,1,117,26,0, + 0,0,95,76,111,97,100,101,114,66,97,115,105,99,115,46, + 95,108,111,97,100,95,109,111,100,117,108,101,78,70,40,9, + 0,0,0,117,8,0,0,0,95,95,110,97,109,101,95,95, + 117,10,0,0,0,95,95,109,111,100,117,108,101,95,95,117, + 12,0,0,0,95,95,113,117,97,108,110,97,109,101,95,95, + 117,7,0,0,0,95,95,100,111,99,95,95,117,10,0,0, + 0,105,115,95,112,97,99,107,97,103,101,117,20,0,0,0, + 95,98,121,116,101,115,95,102,114,111,109,95,98,121,116,101, + 99,111,100,101,117,17,0,0,0,109,111,100,117,108,101,95, + 102,111,114,95,108,111,97,100,101,114,117,5,0,0,0,70, + 97,108,115,101,117,12,0,0,0,95,108,111,97,100,95,109, + 111,100,117,108,101,40,1,0,0,0,117,10,0,0,0,95, + 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,13,0,0,0,95,76,111,97,100,101, + 114,66,97,115,105,99,115,117,1,0,0,115,10,0,0,0, + 16,3,6,2,12,6,12,45,6,1,117,13,0,0,0,95, + 76,111,97,100,101,114,66,97,115,105,99,115,99,1,0,0, + 0,0,0,0,0,1,0,0,0,2,0,0,0,66,0,0, + 0,115,92,0,0,0,124,0,0,69,101,0,0,90,1,0, + 100,0,0,90,2,0,100,1,0,100,2,0,132,0,0,90, + 3,0,100,3,0,100,4,0,132,0,0,90,4,0,100,5, + 0,100,6,0,132,0,0,90,5,0,100,7,0,100,8,0, + 132,0,0,90,6,0,100,9,0,100,10,0,132,0,0,90, + 7,0,100,11,0,100,12,0,132,0,0,90,8,0,100,13, + 0,83,40,14,0,0,0,117,12,0,0,0,83,111,117,114, + 99,101,76,111,97,100,101,114,99,2,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,115,10,0, + 0,0,116,0,0,130,1,0,100,1,0,83,40,2,0,0, + 0,117,121,0,0,0,79,112,116,105,111,110,97,108,32,109, + 101,116,104,111,100,32,116,104,97,116,32,114,101,116,117,114, + 110,115,32,116,104,101,32,109,111,100,105,102,105,99,97,116, + 105,111,110,32,116,105,109,101,32,40,97,110,32,105,110,116, + 41,32,102,111,114,32,116,104,101,10,32,32,32,32,32,32, + 32,32,115,112,101,99,105,102,105,101,100,32,112,97,116,104, + 44,32,119,104,101,114,101,32,112,97,116,104,32,105,115,32, + 97,32,115,116,114,46,10,32,32,32,32,32,32,32,32,78, + 40,1,0,0,0,117,19,0,0,0,78,111,116,73,109,112, + 108,101,109,101,110,116,101,100,69,114,114,111,114,40,2,0, + 0,0,117,4,0,0,0,115,101,108,102,117,4,0,0,0, + 112,97,116,104,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,10,0,0,0,112,97,116,104,95,109,116,105,109,101,196, + 1,0,0,115,2,0,0,0,0,4,117,23,0,0,0,83, + 111,117,114,99,101,76,111,97,100,101,114,46,112,97,116,104, + 95,109,116,105,109,101,99,2,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,67,0,0,0,115,20,0,0,0, + 105,1,0,124,0,0,106,0,0,124,1,0,131,1,0,100, + 1,0,54,83,40,2,0,0,0,117,114,1,0,0,79,112, + 116,105,111,110,97,108,32,109,101,116,104,111,100,32,114,101, + 116,117,114,110,105,110,103,32,97,32,109,101,116,97,100,97, + 116,97,32,100,105,99,116,32,102,111,114,32,116,104,101,32, + 115,112,101,99,105,102,105,101,100,32,112,97,116,104,10,32, + 32,32,32,32,32,32,32,116,111,32,98,121,32,116,104,101, + 32,112,97,116,104,32,40,115,116,114,41,46,10,32,32,32, + 32,32,32,32,32,80,111,115,115,105,98,108,101,32,107,101, + 121,115,58,10,32,32,32,32,32,32,32,32,45,32,39,109, + 116,105,109,101,39,32,40,109,97,110,100,97,116,111,114,121, + 41,32,105,115,32,116,104,101,32,110,117,109,101,114,105,99, + 32,116,105,109,101,115,116,97,109,112,32,111,102,32,108,97, + 115,116,32,115,111,117,114,99,101,10,32,32,32,32,32,32, + 32,32,32,32,99,111,100,101,32,109,111,100,105,102,105,99, + 97,116,105,111,110,59,10,32,32,32,32,32,32,32,32,45, + 32,39,115,105,122,101,39,32,40,111,112,116,105,111,110,97, + 108,41,32,105,115,32,116,104,101,32,115,105,122,101,32,105, + 110,32,98,121,116,101,115,32,111,102,32,116,104,101,32,115, + 111,117,114,99,101,32,99,111,100,101,46,10,10,32,32,32, + 32,32,32,32,32,73,109,112,108,101,109,101,110,116,105,110, + 103,32,116,104,105,115,32,109,101,116,104,111,100,32,97,108, + 108,111,119,115,32,116,104,101,32,108,111,97,100,101,114,32, + 116,111,32,114,101,97,100,32,98,121,116,101,99,111,100,101, + 32,102,105,108,101,115,46,10,32,32,32,32,32,32,32,32, + 117,5,0,0,0,109,116,105,109,101,40,1,0,0,0,117, + 10,0,0,0,112,97,116,104,95,109,116,105,109,101,40,2, + 0,0,0,117,4,0,0,0,115,101,108,102,117,4,0,0, + 0,112,97,116,104,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,10,0,0,0,112,97,116,104,95,115,116,97,116,115, + 202,1,0,0,115,2,0,0,0,0,10,117,23,0,0,0, + 83,111,117,114,99,101,76,111,97,100,101,114,46,112,97,116, + 104,95,115,116,97,116,115,99,3,0,0,0,0,0,0,0, + 3,0,0,0,1,0,0,0,67,0,0,0,115,10,0,0, + 0,116,0,0,130,1,0,100,1,0,83,40,2,0,0,0, + 117,151,0,0,0,79,112,116,105,111,110,97,108,32,109,101, + 116,104,111,100,32,119,104,105,99,104,32,119,114,105,116,101, + 115,32,100,97,116,97,32,40,98,121,116,101,115,41,32,116, + 111,32,97,32,102,105,108,101,32,112,97,116,104,32,40,97, + 32,115,116,114,41,46,10,10,32,32,32,32,32,32,32,32, + 73,109,112,108,101,109,101,110,116,105,110,103,32,116,104,105, + 115,32,109,101,116,104,111,100,32,97,108,108,111,119,115,32, + 102,111,114,32,116,104,101,32,119,114,105,116,105,110,103,32, + 111,102,32,98,121,116,101,99,111,100,101,32,102,105,108,101, + 115,46,10,10,32,32,32,32,32,32,32,32,78,40,1,0, + 0,0,117,19,0,0,0,78,111,116,73,109,112,108,101,109, + 101,110,116,101,100,69,114,114,111,114,40,3,0,0,0,117, + 4,0,0,0,115,101,108,102,117,4,0,0,0,112,97,116, + 104,117,4,0,0,0,100,97,116,97,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,8,0,0,0,115,101,116,95,100, + 97,116,97,214,1,0,0,115,2,0,0,0,0,6,117,21, + 0,0,0,83,111,117,114,99,101,76,111,97,100,101,114,46, + 115,101,116,95,100,97,116,97,99,2,0,0,0,0,0,0, + 0,7,0,0,0,12,0,0,0,67,0,0,0,115,156,0, + 0,0,100,1,0,100,2,0,108,0,0,125,2,0,124,0, + 0,106,1,0,124,1,0,131,1,0,125,3,0,121,19,0, + 124,0,0,106,2,0,124,3,0,131,1,0,125,4,0,87, + 110,36,0,4,116,3,0,107,10,0,114,84,0,1,1,1, + 116,4,0,100,3,0,100,4,0,124,1,0,131,1,1,130, + 1,0,89,110,1,0,88,124,2,0,106,5,0,116,6,0, + 106,7,0,124,4,0,131,1,0,106,8,0,131,1,0,125, + 5,0,116,6,0,106,9,0,100,2,0,100,5,0,131,2, + 0,125,6,0,124,6,0,106,12,0,124,4,0,106,12,0, + 124,5,0,100,1,0,25,131,1,0,131,1,0,83,40,6, + 0,0,0,117,52,0,0,0,67,111,110,99,114,101,116,101, + 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, + 111,102,32,73,110,115,112,101,99,116,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,46,105,0,0,0, + 0,78,117,39,0,0,0,115,111,117,114,99,101,32,110,111, + 116,32,97,118,97,105,108,97,98,108,101,32,116,104,114,111, + 117,103,104,32,103,101,116,95,100,97,116,97,40,41,117,4, + 0,0,0,110,97,109,101,84,40,13,0,0,0,117,8,0, + 0,0,116,111,107,101,110,105,122,101,117,12,0,0,0,103, + 101,116,95,102,105,108,101,110,97,109,101,117,8,0,0,0, + 103,101,116,95,100,97,116,97,117,7,0,0,0,73,79,69, + 114,114,111,114,117,11,0,0,0,73,109,112,111,114,116,69, + 114,114,111,114,117,15,0,0,0,100,101,116,101,99,116,95, + 101,110,99,111,100,105,110,103,117,3,0,0,0,95,105,111, + 117,7,0,0,0,66,121,116,101,115,73,79,117,8,0,0, + 0,114,101,97,100,108,105,110,101,117,25,0,0,0,73,110, + 99,114,101,109,101,110,116,97,108,78,101,119,108,105,110,101, + 68,101,99,111,100,101,114,117,4,0,0,0,78,111,110,101, + 117,4,0,0,0,84,114,117,101,117,6,0,0,0,100,101, + 99,111,100,101,40,7,0,0,0,117,4,0,0,0,115,101, + 108,102,117,8,0,0,0,102,117,108,108,110,97,109,101,117, + 8,0,0,0,116,111,107,101,110,105,122,101,117,4,0,0, + 0,112,97,116,104,117,12,0,0,0,115,111,117,114,99,101, + 95,98,121,116,101,115,117,8,0,0,0,101,110,99,111,100, + 105,110,103,117,15,0,0,0,110,101,119,108,105,110,101,95, + 100,101,99,111,100,101,114,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,10,0,0,0,103,101,116,95,115,111,117,114, + 99,101,223,1,0,0,115,20,0,0,0,0,2,12,1,15, + 1,3,1,19,1,13,1,9,1,14,1,27,1,18,1,117, + 23,0,0,0,83,111,117,114,99,101,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, + 0,0,0,0,12,0,0,0,37,0,0,0,67,0,0,0, + 115,39,2,0,0,124,0,0,106,0,0,124,1,0,131,1, + 0,125,2,0,116,1,0,106,2,0,124,2,0,131,1,0, + 125,3,0,100,10,0,125,4,0,124,3,0,100,10,0,107, + 9,0,114,64,1,121,19,0,124,0,0,106,4,0,124,2, + 0,131,1,0,125,5,0,87,110,18,0,4,116,5,0,107, + 10,0,114,87,0,1,1,1,89,113,64,1,88,116,6,0, + 124,5,0,100,1,0,25,131,1,0,125,4,0,121,19,0, + 124,0,0,106,7,0,124,3,0,131,1,0,125,6,0,87, + 110,18,0,4,116,8,0,107,10,0,114,143,0,1,1,1, + 89,113,64,1,88,121,28,0,124,0,0,106,9,0,124,1, + 0,124,6,0,124,3,0,124,5,0,131,4,0,125,7,0, + 87,110,24,0,4,116,10,0,116,11,0,102,2,0,107,10, + 0,114,198,0,1,1,1,89,113,64,1,88,116,12,0,100, + 2,0,124,3,0,124,2,0,131,3,0,1,116,13,0,106, + 14,0,124,7,0,131,1,0,125,8,0,116,15,0,124,8, + 0,116,16,0,131,2,0,114,22,1,116,1,0,106,17,0, + 124,8,0,124,2,0,131,2,0,1,116,12,0,100,3,0, + 124,3,0,131,2,0,1,124,8,0,83,100,4,0,125,9, + 0,116,10,0,124,9,0,106,18,0,124,3,0,131,1,0, + 100,5,0,124,1,0,100,6,0,124,3,0,131,1,2,130, + 1,0,110,0,0,124,0,0,106,7,0,124,2,0,131,1, + 0,125,10,0,116,19,0,124,10,0,124,2,0,100,7,0, + 100,8,0,100,11,0,131,3,1,125,11,0,116,12,0,100, + 3,0,124,2,0,131,2,0,1,116,21,0,106,22,0,12, + 114,35,2,124,3,0,100,10,0,107,9,0,114,35,2,124, + 4,0,100,10,0,107,9,0,114,35,2,116,23,0,116,1, + 0,106,24,0,131,0,0,131,1,0,125,6,0,124,6,0, + 106,25,0,116,26,0,124,4,0,131,1,0,131,1,0,1, + 124,6,0,106,25,0,116,26,0,116,27,0,124,10,0,131, + 1,0,131,1,0,131,1,0,1,124,6,0,106,25,0,116, + 13,0,106,28,0,124,11,0,131,1,0,131,1,0,1,121, + 33,0,124,0,0,106,29,0,124,3,0,124,6,0,131,2, + 0,1,116,12,0,100,9,0,124,3,0,131,2,0,1,87, + 113,35,2,4,116,5,0,107,10,0,114,31,2,1,1,1, + 89,113,35,2,88,110,0,0,124,11,0,83,40,12,0,0, + 0,117,190,0,0,0,67,111,110,99,114,101,116,101,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, + 32,73,110,115,112,101,99,116,76,111,97,100,101,114,46,103, + 101,116,95,99,111,100,101,46,10,10,32,32,32,32,32,32, + 32,32,82,101,97,100,105,110,103,32,111,102,32,98,121,116, + 101,99,111,100,101,32,114,101,113,117,105,114,101,115,32,112, + 97,116,104,95,115,116,97,116,115,32,116,111,32,98,101,32, + 105,109,112,108,101,109,101,110,116,101,100,46,32,84,111,32, + 119,114,105,116,101,10,32,32,32,32,32,32,32,32,98,121, + 116,101,99,111,100,101,44,32,115,101,116,95,100,97,116,97, + 32,109,117,115,116,32,97,108,115,111,32,98,101,32,105,109, + 112,108,101,109,101,110,116,101,100,46,10,10,32,32,32,32, + 32,32,32,32,117,5,0,0,0,109,116,105,109,101,117,13, + 0,0,0,123,125,32,109,97,116,99,104,101,115,32,123,125, + 117,19,0,0,0,99,111,100,101,32,111,98,106,101,99,116, + 32,102,114,111,109,32,123,125,117,21,0,0,0,78,111,110, + 45,99,111,100,101,32,111,98,106,101,99,116,32,105,110,32, + 123,125,117,4,0,0,0,110,97,109,101,117,4,0,0,0, + 112,97,116,104,117,4,0,0,0,101,120,101,99,117,12,0, + 0,0,100,111,110,116,95,105,110,104,101,114,105,116,117,10, + 0,0,0,119,114,111,116,101,32,123,33,114,125,78,84,40, + 30,0,0,0,117,12,0,0,0,103,101,116,95,102,105,108, + 101,110,97,109,101,117,3,0,0,0,105,109,112,117,17,0, + 0,0,99,97,99,104,101,95,102,114,111,109,95,115,111,117, + 114,99,101,117,4,0,0,0,78,111,110,101,117,10,0,0, + 0,112,97,116,104,95,115,116,97,116,115,117,19,0,0,0, + 78,111,116,73,109,112,108,101,109,101,110,116,101,100,69,114, + 114,111,114,117,3,0,0,0,105,110,116,117,8,0,0,0, + 103,101,116,95,100,97,116,97,117,7,0,0,0,73,79,69, + 114,114,111,114,117,20,0,0,0,95,98,121,116,101,115,95, + 102,114,111,109,95,98,121,116,101,99,111,100,101,117,11,0, + 0,0,73,109,112,111,114,116,69,114,114,111,114,117,8,0, + 0,0,69,79,70,69,114,114,111,114,117,15,0,0,0,118, + 101,114,98,111,115,101,95,109,101,115,115,97,103,101,117,7, + 0,0,0,109,97,114,115,104,97,108,117,5,0,0,0,108, + 111,97,100,115,117,10,0,0,0,105,115,105,110,115,116,97, + 110,99,101,117,9,0,0,0,99,111,100,101,95,116,121,112, + 101,117,16,0,0,0,95,102,105,120,95,99,111,95,102,105, + 108,101,110,97,109,101,117,6,0,0,0,102,111,114,109,97, + 116,117,7,0,0,0,99,111,109,112,105,108,101,117,4,0, + 0,0,84,114,117,101,117,3,0,0,0,115,121,115,117,19, + 0,0,0,100,111,110,116,95,119,114,105,116,101,95,98,121, + 116,101,99,111,100,101,117,9,0,0,0,98,121,116,101,97, + 114,114,97,121,117,9,0,0,0,103,101,116,95,109,97,103, + 105,99,117,6,0,0,0,101,120,116,101,110,100,117,7,0, + 0,0,95,119,95,108,111,110,103,117,3,0,0,0,108,101, + 110,117,5,0,0,0,100,117,109,112,115,117,8,0,0,0, + 115,101,116,95,100,97,116,97,40,12,0,0,0,117,4,0, + 0,0,115,101,108,102,117,8,0,0,0,102,117,108,108,110, + 97,109,101,117,11,0,0,0,115,111,117,114,99,101,95,112, + 97,116,104,117,13,0,0,0,98,121,116,101,99,111,100,101, + 95,112,97,116,104,117,12,0,0,0,115,111,117,114,99,101, + 95,109,116,105,109,101,117,2,0,0,0,115,116,117,4,0, + 0,0,100,97,116,97,117,10,0,0,0,98,121,116,101,115, + 95,100,97,116,97,117,5,0,0,0,102,111,117,110,100,117, + 3,0,0,0,109,115,103,117,12,0,0,0,115,111,117,114, + 99,101,95,98,121,116,101,115,117,11,0,0,0,99,111,100, + 101,95,111,98,106,101,99,116,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,8,0,0,0,103,101,116,95,99,111,100, + 101,236,1,0,0,115,92,0,0,0,0,7,15,1,15,1, + 6,1,12,1,3,1,19,1,13,1,5,2,16,1,3,1, + 19,1,13,1,5,2,3,1,12,1,3,1,13,1,19,1, + 5,2,9,1,7,1,15,1,15,1,16,1,6,1,7,1, + 4,2,6,1,18,1,18,1,15,1,15,1,9,1,13,1, + 22,1,12,4,18,1,19,1,25,1,22,1,3,1,16,1, + 17,1,13,1,8,1,117,21,0,0,0,83,111,117,114,99, + 101,76,111,97,100,101,114,46,103,101,116,95,99,111,100,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, + 0,67,0,0,0,115,13,0,0,0,124,0,0,106,0,0, + 124,1,0,131,1,0,83,40,1,0,0,0,117,0,1,0, + 0,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,111,102,32,76,111,97,100, + 101,114,46,108,111,97,100,95,109,111,100,117,108,101,46,10, + 10,32,32,32,32,32,32,32,32,82,101,113,117,105,114,101, + 115,32,69,120,101,99,117,116,105,111,110,76,111,97,100,101, + 114,46,103,101,116,95,102,105,108,101,110,97,109,101,32,97, + 110,100,32,82,101,115,111,117,114,99,101,76,111,97,100,101, + 114,46,103,101,116,95,100,97,116,97,32,116,111,32,98,101, + 10,32,32,32,32,32,32,32,32,105,109,112,108,101,109,101, + 110,116,101,100,32,116,111,32,108,111,97,100,32,115,111,117, + 114,99,101,32,99,111,100,101,46,32,85,115,101,32,111,102, + 32,98,121,116,101,99,111,100,101,32,105,115,32,100,105,99, + 116,97,116,101,100,32,98,121,32,119,104,101,116,104,101,114, + 10,32,32,32,32,32,32,32,32,103,101,116,95,99,111,100, + 101,32,117,115,101,115,47,119,114,105,116,101,115,32,98,121, + 116,101,99,111,100,101,46,10,10,32,32,32,32,32,32,32, + 32,40,1,0,0,0,117,12,0,0,0,95,108,111,97,100, + 95,109,111,100,117,108,101,40,2,0,0,0,117,4,0,0, + 0,115,101,108,102,117,8,0,0,0,102,117,108,108,110,97, + 109,101,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,11, + 0,0,0,108,111,97,100,95,109,111,100,117,108,101,41,2, + 0,0,115,2,0,0,0,0,8,117,24,0,0,0,83,111, + 117,114,99,101,76,111,97,100,101,114,46,108,111,97,100,95, + 109,111,100,117,108,101,78,40,9,0,0,0,117,8,0,0, + 0,95,95,110,97,109,101,95,95,117,10,0,0,0,95,95, + 109,111,100,117,108,101,95,95,117,12,0,0,0,95,95,113, + 117,97,108,110,97,109,101,95,95,117,10,0,0,0,112,97, + 116,104,95,109,116,105,109,101,117,10,0,0,0,112,97,116, + 104,95,115,116,97,116,115,117,8,0,0,0,115,101,116,95, + 100,97,116,97,117,10,0,0,0,103,101,116,95,115,111,117, + 114,99,101,117,8,0,0,0,103,101,116,95,99,111,100,101, + 117,11,0,0,0,108,111,97,100,95,109,111,100,117,108,101, + 40,1,0,0,0,117,10,0,0,0,95,95,108,111,99,97, + 108,115,95,95,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,12,0,0,0,83,111,117,114,99,101,76,111,97,100,101, + 114,194,1,0,0,115,12,0,0,0,16,2,12,6,12,12, + 12,9,12,13,12,61,117,12,0,0,0,83,111,117,114,99, + 101,76,111,97,100,101,114,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,66,0,0,0,115,68,0,0, + 0,124,0,0,69,101,0,0,90,1,0,100,0,0,90,2, + 0,100,1,0,90,3,0,100,2,0,100,3,0,132,0,0, + 90,4,0,101,5,0,100,4,0,100,5,0,132,0,0,131, + 1,0,90,6,0,100,6,0,100,7,0,132,0,0,90,7, + 0,100,8,0,83,40,9,0,0,0,117,11,0,0,0,95, + 70,105,108,101,76,111,97,100,101,114,117,103,0,0,0,66, + 97,115,101,32,102,105,108,101,32,108,111,97,100,101,114,32, + 99,108,97,115,115,32,119,104,105,99,104,32,105,109,112,108, + 101,109,101,110,116,115,32,116,104,101,32,108,111,97,100,101, + 114,32,112,114,111,116,111,99,111,108,32,109,101,116,104,111, + 100,115,32,116,104,97,116,10,32,32,32,32,114,101,113,117, + 105,114,101,32,102,105,108,101,32,115,121,115,116,101,109,32, + 117,115,97,103,101,46,99,3,0,0,0,0,0,0,0,3, + 0,0,0,2,0,0,0,67,0,0,0,115,22,0,0,0, + 124,1,0,124,0,0,95,0,0,124,2,0,124,0,0,95, + 1,0,100,1,0,83,40,2,0,0,0,117,75,0,0,0, + 67,97,99,104,101,32,116,104,101,32,109,111,100,117,108,101, + 32,110,97,109,101,32,97,110,100,32,116,104,101,32,112,97, + 116,104,32,116,111,32,116,104,101,32,102,105,108,101,32,102, + 111,117,110,100,32,98,121,32,116,104,101,10,32,32,32,32, + 32,32,32,32,102,105,110,100,101,114,46,78,40,2,0,0, + 0,117,5,0,0,0,95,110,97,109,101,117,5,0,0,0, + 95,112,97,116,104,40,3,0,0,0,117,4,0,0,0,115, + 101,108,102,117,8,0,0,0,102,117,108,108,110,97,109,101, + 117,4,0,0,0,112,97,116,104,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,8,0,0,0,95,95,105,110,105,116, + 95,95,57,2,0,0,115,4,0,0,0,0,3,9,1,117, + 20,0,0,0,95,70,105,108,101,76,111,97,100,101,114,46, + 95,95,105,110,105,116,95,95,99,2,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,115,7,0, + 0,0,124,0,0,106,0,0,83,40,1,0,0,0,117,58, + 0,0,0,82,101,116,117,114,110,32,116,104,101,32,112,97, + 116,104,32,116,111,32,116,104,101,32,115,111,117,114,99,101, + 32,102,105,108,101,32,97,115,32,102,111,117,110,100,32,98, + 121,32,116,104,101,32,102,105,110,100,101,114,46,40,1,0, + 0,0,117,5,0,0,0,95,112,97,116,104,40,2,0,0, + 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,102, + 117,108,108,110,97,109,101,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,12,0,0,0,103,101,116,95,102,105,108,101, + 110,97,109,101,63,2,0,0,115,2,0,0,0,0,3,117, + 24,0,0,0,95,70,105,108,101,76,111,97,100,101,114,46, + 103,101,116,95,102,105,108,101,110,97,109,101,99,2,0,0, + 0,0,0,0,0,3,0,0,0,8,0,0,0,67,0,0, + 0,115,41,0,0,0,116,0,0,106,1,0,124,1,0,100, + 1,0,131,2,0,143,17,0,125,2,0,124,2,0,106,2, + 0,131,0,0,83,87,100,2,0,81,88,100,2,0,83,40, + 3,0,0,0,117,39,0,0,0,82,101,116,117,114,110,32, + 116,104,101,32,100,97,116,97,32,102,114,111,109,32,112,97, + 116,104,32,97,115,32,114,97,119,32,98,121,116,101,115,46, + 117,1,0,0,0,114,78,40,3,0,0,0,117,3,0,0, + 0,95,105,111,117,6,0,0,0,70,105,108,101,73,79,117, + 4,0,0,0,114,101,97,100,40,3,0,0,0,117,4,0, + 0,0,115,101,108,102,117,4,0,0,0,112,97,116,104,117, + 4,0,0,0,102,105,108,101,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,8,0,0,0,103,101,116,95,100,97,116, + 97,68,2,0,0,115,4,0,0,0,0,2,21,1,117,20, + 0,0,0,95,70,105,108,101,76,111,97,100,101,114,46,103, + 101,116,95,100,97,116,97,78,40,8,0,0,0,117,8,0, + 0,0,95,95,110,97,109,101,95,95,117,10,0,0,0,95, + 95,109,111,100,117,108,101,95,95,117,12,0,0,0,95,95, + 113,117,97,108,110,97,109,101,95,95,117,7,0,0,0,95, + 95,100,111,99,95,95,117,8,0,0,0,95,95,105,110,105, + 116,95,95,117,11,0,0,0,95,99,104,101,99,107,95,110, + 97,109,101,117,12,0,0,0,103,101,116,95,102,105,108,101, + 110,97,109,101,117,8,0,0,0,103,101,116,95,100,97,116, + 97,40,1,0,0,0,117,10,0,0,0,95,95,108,111,99, + 97,108,115,95,95,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,11,0,0,0,95,70,105,108,101,76,111,97,100,101, + 114,52,2,0,0,115,8,0,0,0,16,3,6,2,12,6, + 18,5,117,11,0,0,0,95,70,105,108,101,76,111,97,100, + 101,114,99,1,0,0,0,0,0,0,0,1,0,0,0,2, + 0,0,0,66,0,0,0,115,50,0,0,0,124,0,0,69, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, + 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, + 0,100,5,0,132,0,0,90,5,0,100,6,0,83,40,7, + 0,0,0,117,17,0,0,0,95,83,111,117,114,99,101,70, + 105,108,101,76,111,97,100,101,114,117,62,0,0,0,67,111, + 110,99,114,101,116,101,32,105,109,112,108,101,109,101,110,116, + 97,116,105,111,110,32,111,102,32,83,111,117,114,99,101,76, + 111,97,100,101,114,32,117,115,105,110,103,32,116,104,101,32, + 102,105,108,101,32,115,121,115,116,101,109,46,99,2,0,0, + 0,0,0,0,0,3,0,0,0,3,0,0,0,67,0,0, + 0,115,39,0,0,0,116,0,0,106,1,0,124,1,0,131, + 1,0,125,2,0,105,2,0,124,2,0,106,2,0,100,1, + 0,54,124,2,0,106,3,0,100,2,0,54,83,40,3,0, + 0,0,117,32,0,0,0,82,101,116,117,114,110,32,116,104, + 101,32,109,101,116,97,100,97,116,32,102,111,114,32,116,104, + 101,32,112,97,116,104,46,117,5,0,0,0,109,116,105,109, + 101,117,4,0,0,0,115,105,122,101,40,4,0,0,0,117, + 3,0,0,0,95,111,115,117,4,0,0,0,115,116,97,116, + 117,8,0,0,0,115,116,95,109,116,105,109,101,117,7,0, + 0,0,115,116,95,115,105,122,101,40,3,0,0,0,117,4, + 0,0,0,115,101,108,102,117,4,0,0,0,112,97,116,104, + 117,2,0,0,0,115,116,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,10,0,0,0,112,97,116,104,95,115,116,97, + 116,115,78,2,0,0,115,4,0,0,0,0,2,15,1,117, + 28,0,0,0,95,83,111,117,114,99,101,70,105,108,101,76, + 111,97,100,101,114,46,112,97,116,104,95,115,116,97,116,115, + 99,3,0,0,0,0,0,0,0,8,0,0,0,13,0,0, + 0,67,0,0,0,115,254,0,0,0,124,1,0,106,0,0, + 116,1,0,131,1,0,92,3,0,125,3,0,125,4,0,125, + 5,0,103,0,0,125,6,0,120,60,0,124,3,0,114,92, + 0,116,2,0,124,3,0,131,1,0,12,114,92,0,124,3, + 0,106,0,0,116,1,0,131,1,0,92,3,0,125,3,0, + 125,4,0,125,7,0,124,6,0,106,3,0,124,7,0,131, + 1,0,1,113,33,0,87,120,97,0,116,4,0,124,6,0, + 131,1,0,68,93,83,0,125,7,0,116,5,0,124,3,0, + 124,7,0,131,2,0,125,3,0,121,17,0,116,6,0,106, + 7,0,124,3,0,131,1,0,1,87,113,106,0,4,116,8, + 0,107,10,0,114,167,0,1,1,1,119,106,0,89,113,106, + 0,4,116,9,0,107,10,0,114,188,0,1,1,1,100,1, + 0,83,89,113,106,0,88,113,106,0,87,121,30,0,116,10, + 0,124,1,0,124,2,0,131,2,0,1,116,11,0,100,2, + 0,124,1,0,131,2,0,1,87,110,24,0,4,116,9,0, + 116,8,0,102,2,0,107,10,0,114,249,0,1,1,1,89, + 110,1,0,88,100,1,0,83,40,3,0,0,0,117,27,0, + 0,0,87,114,105,116,101,32,98,121,116,101,115,32,100,97, + 116,97,32,116,111,32,97,32,102,105,108,101,46,78,117,12, + 0,0,0,99,114,101,97,116,101,100,32,123,33,114,125,40, + 12,0,0,0,117,10,0,0,0,114,112,97,114,116,105,116, + 105,111,110,117,8,0,0,0,112,97,116,104,95,115,101,112, + 117,11,0,0,0,95,112,97,116,104,95,105,115,100,105,114, + 117,6,0,0,0,97,112,112,101,110,100,117,8,0,0,0, + 114,101,118,101,114,115,101,100,117,10,0,0,0,95,112,97, + 116,104,95,106,111,105,110,117,3,0,0,0,95,111,115,117, + 5,0,0,0,109,107,100,105,114,117,15,0,0,0,70,105, + 108,101,69,120,105,115,116,115,69,114,114,111,114,117,15,0, + 0,0,80,101,114,109,105,115,115,105,111,110,69,114,114,111, + 114,117,13,0,0,0,95,119,114,105,116,101,95,97,116,111, + 109,105,99,117,15,0,0,0,118,101,114,98,111,115,101,95, + 109,101,115,115,97,103,101,40,8,0,0,0,117,4,0,0, + 0,115,101,108,102,117,4,0,0,0,112,97,116,104,117,4, + 0,0,0,100,97,116,97,117,6,0,0,0,112,97,114,101, + 110,116,117,1,0,0,0,95,117,8,0,0,0,102,105,108, + 101,110,97,109,101,117,10,0,0,0,112,97,116,104,95,112, + 97,114,116,115,117,4,0,0,0,112,97,114,116,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,8,0,0,0,115,101, + 116,95,100,97,116,97,83,2,0,0,115,36,0,0,0,0, + 2,24,1,6,2,22,1,24,1,17,2,19,1,15,1,3, + 1,17,1,13,2,7,1,13,3,13,1,3,1,13,1,17, + 1,19,3,117,26,0,0,0,95,83,111,117,114,99,101,70, + 105,108,101,76,111,97,100,101,114,46,115,101,116,95,100,97, + 116,97,78,40,6,0,0,0,117,8,0,0,0,95,95,110, + 97,109,101,95,95,117,10,0,0,0,95,95,109,111,100,117, + 108,101,95,95,117,12,0,0,0,95,95,113,117,97,108,110, + 97,109,101,95,95,117,7,0,0,0,95,95,100,111,99,95, + 95,117,10,0,0,0,112,97,116,104,95,115,116,97,116,115, + 117,8,0,0,0,115,101,116,95,100,97,116,97,40,1,0, + 0,0,117,10,0,0,0,95,95,108,111,99,97,108,115,95, + 95,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,17,0, + 0,0,95,83,111,117,114,99,101,70,105,108,101,76,111,97, + 100,101,114,74,2,0,0,115,6,0,0,0,16,2,6,2, + 12,5,117,17,0,0,0,95,83,111,117,114,99,101,70,105, + 108,101,76,111,97,100,101,114,99,1,0,0,0,0,0,0, + 0,1,0,0,0,2,0,0,0,66,0,0,0,115,62,0, + 0,0,124,0,0,69,101,0,0,90,1,0,100,0,0,90, + 2,0,100,1,0,90,3,0,100,2,0,100,3,0,132,0, + 0,90,4,0,100,4,0,100,5,0,132,0,0,90,5,0, + 100,6,0,100,7,0,132,0,0,90,6,0,100,8,0,83, + 40,9,0,0,0,117,21,0,0,0,95,83,111,117,114,99, + 101,108,101,115,115,70,105,108,101,76,111,97,100,101,114,117, + 45,0,0,0,76,111,97,100,101,114,32,119,104,105,99,104, + 32,104,97,110,100,108,101,115,32,115,111,117,114,99,101,108, + 101,115,115,32,102,105,108,101,32,105,109,112,111,114,116,115, + 46,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0, + 0,0,67,0,0,0,115,19,0,0,0,124,0,0,106,0, + 0,124,1,0,100,1,0,100,2,0,131,1,1,83,40,3, + 0,0,0,78,117,10,0,0,0,115,111,117,114,99,101,108, + 101,115,115,84,40,2,0,0,0,117,12,0,0,0,95,108, + 111,97,100,95,109,111,100,117,108,101,117,4,0,0,0,84, + 114,117,101,40,2,0,0,0,117,4,0,0,0,115,101,108, + 102,117,8,0,0,0,102,117,108,108,110,97,109,101,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,11,0,0,0,108, + 111,97,100,95,109,111,100,117,108,101,116,2,0,0,115,2, + 0,0,0,0,1,117,33,0,0,0,95,83,111,117,114,99, + 101,108,101,115,115,70,105,108,101,76,111,97,100,101,114,46, + 108,111,97,100,95,109,111,100,117,108,101,99,2,0,0,0, + 0,0,0,0,6,0,0,0,6,0,0,0,67,0,0,0, + 115,138,0,0,0,124,0,0,106,0,0,124,1,0,131,1, + 0,125,2,0,124,0,0,106,1,0,124,2,0,131,1,0, + 125,3,0,124,0,0,106,2,0,124,1,0,124,3,0,124, + 2,0,100,0,0,131,4,0,125,4,0,116,4,0,106,5, + 0,124,4,0,131,1,0,125,5,0,116,6,0,124,5,0, + 116,7,0,131,2,0,114,101,0,116,8,0,100,1,0,124, + 2,0,131,2,0,1,124,5,0,83,116,9,0,100,2,0, + 106,10,0,124,2,0,131,1,0,100,3,0,124,1,0,100, + 4,0,124,2,0,131,1,2,130,1,0,100,0,0,83,40, + 5,0,0,0,78,117,21,0,0,0,99,111,100,101,32,111, + 98,106,101,99,116,32,102,114,111,109,32,123,33,114,125,117, + 21,0,0,0,78,111,110,45,99,111,100,101,32,111,98,106, + 101,99,116,32,105,110,32,123,125,117,4,0,0,0,110,97, + 109,101,117,4,0,0,0,112,97,116,104,40,11,0,0,0, + 117,12,0,0,0,103,101,116,95,102,105,108,101,110,97,109, + 101,117,8,0,0,0,103,101,116,95,100,97,116,97,117,20, + 0,0,0,95,98,121,116,101,115,95,102,114,111,109,95,98, + 121,116,101,99,111,100,101,117,4,0,0,0,78,111,110,101, + 117,7,0,0,0,109,97,114,115,104,97,108,117,5,0,0, + 0,108,111,97,100,115,117,10,0,0,0,105,115,105,110,115, + 116,97,110,99,101,117,9,0,0,0,99,111,100,101,95,116, + 121,112,101,117,15,0,0,0,118,101,114,98,111,115,101,95, + 109,101,115,115,97,103,101,117,11,0,0,0,73,109,112,111, + 114,116,69,114,114,111,114,117,6,0,0,0,102,111,114,109, + 97,116,40,6,0,0,0,117,4,0,0,0,115,101,108,102, + 117,8,0,0,0,102,117,108,108,110,97,109,101,117,4,0, + 0,0,112,97,116,104,117,4,0,0,0,100,97,116,97,117, + 10,0,0,0,98,121,116,101,115,95,100,97,116,97,117,5, + 0,0,0,102,111,117,110,100,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,8,0,0,0,103,101,116,95,99,111,100, + 101,119,2,0,0,115,18,0,0,0,0,1,15,1,15,1, + 24,1,15,1,15,1,13,1,4,2,18,1,117,30,0,0, + 0,95,83,111,117,114,99,101,108,101,115,115,70,105,108,101, + 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,99, + 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, + 67,0,0,0,115,4,0,0,0,100,1,0,83,40,2,0, + 0,0,117,39,0,0,0,82,101,116,117,114,110,32,78,111, + 110,101,32,97,115,32,116,104,101,114,101,32,105,115,32,110, + 111,32,115,111,117,114,99,101,32,99,111,100,101,46,78,40, + 1,0,0,0,117,4,0,0,0,78,111,110,101,40,2,0, + 0,0,117,4,0,0,0,115,101,108,102,117,8,0,0,0, + 102,117,108,108,110,97,109,101,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,10,0,0,0,103,101,116,95,115,111,117, + 114,99,101,131,2,0,0,115,2,0,0,0,0,2,117,32, + 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, + 108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,78,40,7,0,0,0,117,8,0,0,0,95,95, + 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, + 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, + 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, + 95,95,117,11,0,0,0,108,111,97,100,95,109,111,100,117, + 108,101,117,8,0,0,0,103,101,116,95,99,111,100,101,117, + 10,0,0,0,103,101,116,95,115,111,117,114,99,101,40,1, + 0,0,0,117,10,0,0,0,95,95,108,111,99,97,108,115, + 95,95,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,21, + 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, + 108,101,76,111,97,100,101,114,112,2,0,0,115,8,0,0, + 0,16,2,6,2,12,3,12,12,117,21,0,0,0,95,83, + 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, + 100,101,114,99,1,0,0,0,0,0,0,0,1,0,0,0, + 5,0,0,0,66,0,0,0,115,122,0,0,0,124,0,0, + 69,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, + 90,3,0,100,2,0,100,3,0,132,0,0,90,4,0,101, + 5,0,101,6,0,101,7,0,100,4,0,100,5,0,132,0, + 0,131,1,0,131,1,0,131,1,0,90,8,0,101,5,0, + 100,6,0,100,7,0,132,0,0,131,1,0,90,9,0,101, + 5,0,100,8,0,100,9,0,132,0,0,131,1,0,90,10, + 0,101,5,0,100,10,0,100,11,0,132,0,0,131,1,0, + 90,11,0,100,12,0,83,40,13,0,0,0,117,20,0,0, + 0,95,69,120,116,101,110,115,105,111,110,70,105,108,101,76, + 111,97,100,101,114,117,93,0,0,0,76,111,97,100,101,114, + 32,102,111,114,32,101,120,116,101,110,115,105,111,110,32,109, + 111,100,117,108,101,115,46,10,10,32,32,32,32,84,104,101, + 32,99,111,110,115,116,114,117,99,116,111,114,32,105,115,32, + 100,101,115,105,103,110,101,100,32,116,111,32,119,111,114,107, + 32,119,105,116,104,32,70,105,108,101,70,105,110,100,101,114, + 46,10,10,32,32,32,32,99,3,0,0,0,0,0,0,0, + 3,0,0,0,2,0,0,0,67,0,0,0,115,22,0,0, + 0,124,1,0,124,0,0,95,0,0,124,2,0,124,0,0, + 95,1,0,100,0,0,83,40,1,0,0,0,78,40,2,0, + 0,0,117,5,0,0,0,95,110,97,109,101,117,5,0,0, + 0,95,112,97,116,104,40,3,0,0,0,117,4,0,0,0, + 115,101,108,102,117,4,0,0,0,110,97,109,101,117,4,0, + 0,0,112,97,116,104,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,8,0,0,0,95,95,105,110,105,116,95,95,144, + 2,0,0,115,4,0,0,0,0,1,9,1,117,29,0,0, + 0,95,69,120,116,101,110,115,105,111,110,70,105,108,101,76, + 111,97,100,101,114,46,95,95,105,110,105,116,95,95,99,2, + 0,0,0,0,0,0,0,4,0,0,0,9,0,0,0,67, + 0,0,0,115,113,0,0,0,124,1,0,116,0,0,106,1, + 0,107,6,0,125,2,0,121,45,0,116,2,0,106,3,0, + 124,1,0,124,0,0,106,4,0,131,2,0,125,3,0,116, + 5,0,100,1,0,124,0,0,106,4,0,131,2,0,1,124, + 3,0,83,87,110,46,0,1,1,1,124,2,0,12,114,101, + 0,124,1,0,116,0,0,106,1,0,107,6,0,114,101,0, + 116,0,0,106,1,0,124,1,0,61,110,0,0,130,0,0, + 89,110,1,0,88,100,2,0,83,40,3,0,0,0,117,25, + 0,0,0,76,111,97,100,32,97,110,32,101,120,116,101,110, + 115,105,111,110,32,109,111,100,117,108,101,46,117,33,0,0, + 0,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, + 101,32,108,111,97,100,101,100,32,102,114,111,109,32,123,33, + 114,125,78,40,6,0,0,0,117,3,0,0,0,115,121,115, + 117,7,0,0,0,109,111,100,117,108,101,115,117,3,0,0, + 0,105,109,112,117,12,0,0,0,108,111,97,100,95,100,121, + 110,97,109,105,99,117,5,0,0,0,95,112,97,116,104,117, + 15,0,0,0,118,101,114,98,111,115,101,95,109,101,115,115, + 97,103,101,40,4,0,0,0,117,4,0,0,0,115,101,108, + 102,117,8,0,0,0,102,117,108,108,110,97,109,101,117,9, + 0,0,0,105,115,95,114,101,108,111,97,100,117,6,0,0, + 0,109,111,100,117,108,101,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,11,0,0,0,108,111,97,100,95,109,111,100, + 117,108,101,148,2,0,0,115,18,0,0,0,0,5,15,1, + 3,1,21,1,16,1,8,1,3,1,22,1,13,1,117,32, + 0,0,0,95,69,120,116,101,110,115,105,111,110,70,105,108, + 101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,100, + 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,0, + 83,40,2,0,0,0,117,59,0,0,0,82,101,116,117,114, + 110,32,70,97,108,115,101,32,97,115,32,97,110,32,101,120, + 116,101,110,115,105,111,110,32,109,111,100,117,108,101,32,99, + 97,110,32,110,101,118,101,114,32,98,101,32,97,32,112,97, + 99,107,97,103,101,46,70,40,1,0,0,0,117,5,0,0, + 0,70,97,108,115,101,40,2,0,0,0,117,4,0,0,0, + 115,101,108,102,117,8,0,0,0,102,117,108,108,110,97,109, + 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,10,0, + 0,0,105,115,95,112,97,99,107,97,103,101,163,2,0,0, + 115,2,0,0,0,0,3,117,31,0,0,0,95,69,120,116, + 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, + 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,0,83,40,2,0,0,0,117,63, + 0,0,0,82,101,116,117,114,110,32,78,111,110,101,32,97, + 115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,109, + 111,100,117,108,101,32,99,97,110,110,111,116,32,99,114,101, + 97,116,101,32,97,32,99,111,100,101,32,111,98,106,101,99, + 116,46,78,40,1,0,0,0,117,4,0,0,0,78,111,110, + 101,40,2,0,0,0,117,4,0,0,0,115,101,108,102,117, + 8,0,0,0,102,117,108,108,110,97,109,101,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,8,0,0,0,103,101,116, + 95,99,111,100,101,168,2,0,0,115,2,0,0,0,0,3, + 117,29,0,0,0,95,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,46,103,101,116,95,99,111, + 100,101,99,2,0,0,0,0,0,0,0,2,0,0,0,1, + 0,0,0,67,0,0,0,115,4,0,0,0,100,1,0,83, + 40,2,0,0,0,117,53,0,0,0,82,101,116,117,114,110, + 32,78,111,110,101,32,97,115,32,101,120,116,101,110,115,105, + 111,110,32,109,111,100,117,108,101,115,32,104,97,118,101,32, + 110,111,32,115,111,117,114,99,101,32,99,111,100,101,46,78, + 40,1,0,0,0,117,4,0,0,0,78,111,110,101,40,2, + 0,0,0,117,4,0,0,0,115,101,108,102,117,8,0,0, + 0,102,117,108,108,110,97,109,101,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,10,0,0,0,103,101,116,95,115,111, + 117,114,99,101,173,2,0,0,115,2,0,0,0,0,3,117, + 31,0,0,0,95,69,120,116,101,110,115,105,111,110,70,105, + 108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,78,40,12,0,0,0,117,8,0,0,0,95,95, + 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, + 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, + 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, + 95,95,117,8,0,0,0,95,95,105,110,105,116,95,95,117, + 11,0,0,0,95,99,104,101,99,107,95,110,97,109,101,117, + 11,0,0,0,115,101,116,95,112,97,99,107,97,103,101,117, + 10,0,0,0,115,101,116,95,108,111,97,100,101,114,117,11, + 0,0,0,108,111,97,100,95,109,111,100,117,108,101,117,10, + 0,0,0,105,115,95,112,97,99,107,97,103,101,117,8,0, + 0,0,103,101,116,95,99,111,100,101,117,10,0,0,0,103, + 101,116,95,115,111,117,114,99,101,40,1,0,0,0,117,10, + 0,0,0,95,95,108,111,99,97,108,115,95,95,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,20,0,0,0,95,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,136,2,0,0,115,16,0,0,0,16,6,6,2,12, + 4,3,1,3,1,24,13,18,5,18,5,117,20,0,0,0, + 95,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, + 97,100,101,114,99,1,0,0,0,0,0,0,0,1,0,0, + 0,4,0,0,0,66,0,0,0,115,89,0,0,0,124,0, + 0,69,101,0,0,90,1,0,100,0,0,90,2,0,100,1, + 0,90,3,0,101,4,0,100,8,0,100,2,0,100,3,0, + 132,1,0,131,1,0,90,6,0,101,4,0,100,8,0,100, + 4,0,100,5,0,132,1,0,131,1,0,90,7,0,101,4, + 0,100,8,0,100,6,0,100,7,0,132,1,0,131,1,0, + 90,8,0,100,8,0,83,40,9,0,0,0,117,10,0,0, + 0,80,97,116,104,70,105,110,100,101,114,117,63,0,0,0, + 77,101,116,97,32,112,97,116,104,32,102,105,110,100,101,114, + 32,102,111,114,32,115,121,115,46,40,112,97,116,104,124,112, + 97,116,104,95,104,111,111,107,115,124,112,97,116,104,95,105, + 109,112,111,114,116,101,114,95,99,97,99,104,101,41,46,99, + 3,0,0,0,0,0,0,0,4,0,0,0,12,0,0,0, + 67,0,0,0,115,104,0,0,0,124,2,0,115,18,0,116, + 0,0,106,1,0,125,2,0,110,0,0,120,79,0,124,2, + 0,68,93,44,0,125,3,0,121,14,0,124,3,0,124,1, + 0,131,1,0,83,87,113,25,0,4,116,2,0,107,10,0, + 114,68,0,1,1,1,119,25,0,89,113,25,0,88,113,25, + 0,87,116,2,0,100,1,0,106,3,0,124,1,0,131,1, + 0,100,2,0,124,1,0,131,1,1,130,1,0,100,3,0, + 83,40,4,0,0,0,117,113,0,0,0,83,101,97,114,99, + 104,32,115,101,113,117,101,110,99,101,32,111,102,32,104,111, + 111,107,115,32,102,111,114,32,97,32,102,105,110,100,101,114, + 32,102,111,114,32,39,112,97,116,104,39,46,10,10,32,32, + 32,32,32,32,32,32,73,102,32,39,104,111,111,107,115,39, + 32,105,115,32,102,97,108,115,101,32,116,104,101,110,32,117, + 115,101,32,115,121,115,46,112,97,116,104,95,104,111,111,107, + 115,46,10,10,32,32,32,32,32,32,32,32,117,26,0,0, + 0,110,111,32,112,97,116,104,32,104,111,111,107,32,102,111, + 117,110,100,32,102,111,114,32,123,48,125,117,4,0,0,0, + 112,97,116,104,78,40,4,0,0,0,117,3,0,0,0,115, + 121,115,117,10,0,0,0,112,97,116,104,95,104,111,111,107, + 115,117,11,0,0,0,73,109,112,111,114,116,69,114,114,111, + 114,117,6,0,0,0,102,111,114,109,97,116,40,4,0,0, + 0,117,3,0,0,0,99,108,115,117,4,0,0,0,112,97, + 116,104,117,5,0,0,0,104,111,111,107,115,117,4,0,0, + 0,104,111,111,107,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,11,0,0,0,95,112,97,116,104,95,104,111,111,107, + 115,185,2,0,0,115,18,0,0,0,0,7,6,1,12,1, + 13,1,3,1,14,1,13,1,12,2,18,1,117,22,0,0, + 0,80,97,116,104,70,105,110,100,101,114,46,95,112,97,116, + 104,95,104,111,111,107,115,99,3,0,0,0,0,0,0,0, + 4,0,0,0,12,0,0,0,67,0,0,0,115,137,0,0, + 0,124,1,0,100,1,0,107,2,0,114,21,0,100,2,0, + 125,1,0,110,0,0,121,17,0,116,0,0,106,1,0,124, + 1,0,25,125,3,0,87,110,46,0,4,116,2,0,107,10, + 0,114,86,0,1,1,1,124,0,0,106,3,0,124,1,0, + 131,1,0,125,3,0,124,3,0,116,0,0,106,1,0,124, + 1,0,60,89,110,47,0,88,124,3,0,100,3,0,107,8, + 0,114,133,0,124,2,0,114,133,0,124,2,0,124,1,0, + 131,1,0,125,3,0,124,3,0,116,0,0,106,1,0,124, + 1,0,60,110,0,0,124,3,0,83,40,4,0,0,0,117, + 199,1,0,0,71,101,116,32,116,104,101,32,102,105,110,100, + 101,114,32,102,111,114,32,116,104,101,32,112,97,116,104,32, + 102,114,111,109,32,115,121,115,46,112,97,116,104,95,105,109, + 112,111,114,116,101,114,95,99,97,99,104,101,46,10,10,32, + 32,32,32,32,32,32,32,73,102,32,116,104,101,32,112,97, + 116,104,32,105,115,32,110,111,116,32,105,110,32,116,104,101, + 32,99,97,99,104,101,44,32,102,105,110,100,32,116,104,101, + 32,97,112,112,114,111,112,114,105,97,116,101,32,102,105,110, + 100,101,114,32,97,110,100,32,99,97,99,104,101,10,32,32, + 32,32,32,32,32,32,105,116,46,32,73,102,32,78,111,110, + 101,32,105,115,32,99,97,99,104,101,100,44,32,103,101,116, + 32,116,104,101,32,100,101,102,97,117,108,116,32,102,105,110, + 100,101,114,32,97,110,100,32,99,97,99,104,101,32,116,104, + 97,116,10,32,32,32,32,32,32,32,32,40,105,102,32,97, + 112,112,108,105,99,97,98,108,101,41,46,10,10,32,32,32, + 32,32,32,32,32,66,101,99,97,117,115,101,32,111,102,32, + 78,117,108,108,73,109,112,111,114,116,101,114,44,32,115,111, + 109,101,32,102,105,110,100,101,114,32,115,104,111,117,108,100, + 32,98,101,32,114,101,116,117,114,110,101,100,46,32,84,104, + 101,32,111,110,108,121,10,32,32,32,32,32,32,32,32,101, + 120,112,108,105,99,105,116,32,102,97,105,108,32,99,97,115, + 101,32,105,115,32,105,102,32,78,111,110,101,32,105,115,32, + 99,97,99,104,101,100,32,98,117,116,32,116,104,101,32,112, + 97,116,104,32,99,97,110,110,111,116,32,98,101,32,117,115, + 101,100,32,102,111,114,10,32,32,32,32,32,32,32,32,116, + 104,101,32,100,101,102,97,117,108,116,32,104,111,111,107,44, + 32,102,111,114,32,119,104,105,99,104,32,73,109,112,111,114, + 116,69,114,114,111,114,32,105,115,32,114,97,105,115,101,100, + 46,10,10,32,32,32,32,32,32,32,32,117,0,0,0,0, + 117,1,0,0,0,46,78,40,5,0,0,0,117,3,0,0, + 0,115,121,115,117,19,0,0,0,112,97,116,104,95,105,109, + 112,111,114,116,101,114,95,99,97,99,104,101,117,8,0,0, + 0,75,101,121,69,114,114,111,114,117,11,0,0,0,95,112, + 97,116,104,95,104,111,111,107,115,117,4,0,0,0,78,111, + 110,101,40,4,0,0,0,117,3,0,0,0,99,108,115,117, + 4,0,0,0,112,97,116,104,117,7,0,0,0,100,101,102, + 97,117,108,116,117,6,0,0,0,102,105,110,100,101,114,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,20,0,0,0, + 95,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, + 97,99,104,101,203,2,0,0,115,22,0,0,0,0,13,12, + 1,9,1,3,1,17,1,13,1,15,1,18,2,18,2,12, + 1,16,1,117,31,0,0,0,80,97,116,104,70,105,110,100, + 101,114,46,95,112,97,116,104,95,105,109,112,111,114,116,101, + 114,95,99,97,99,104,101,99,3,0,0,0,0,0,0,0, + 6,0,0,0,12,0,0,0,67,0,0,0,115,120,0,0, + 0,124,2,0,115,18,0,116,0,0,106,1,0,125,2,0, + 110,0,0,120,95,0,124,2,0,68,93,83,0,125,3,0, + 121,19,0,124,0,0,106,2,0,124,3,0,131,1,0,125, + 4,0,87,110,21,0,4,116,3,0,107,10,0,114,73,0, + 1,1,1,119,25,0,89,110,1,0,88,124,4,0,114,25, + 0,124,4,0,106,4,0,124,1,0,131,1,0,125,5,0, + 124,5,0,114,108,0,124,5,0,83,113,25,0,113,25,0, + 87,100,1,0,83,100,1,0,83,40,2,0,0,0,117,98, + 0,0,0,70,105,110,100,32,116,104,101,32,109,111,100,117, + 108,101,32,111,110,32,115,121,115,46,112,97,116,104,32,111, + 114,32,39,112,97,116,104,39,32,98,97,115,101,100,32,111, + 110,32,115,121,115,46,112,97,116,104,95,104,111,111,107,115, + 32,97,110,100,10,32,32,32,32,32,32,32,32,115,121,115, + 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, + 97,99,104,101,46,78,40,6,0,0,0,117,3,0,0,0, + 115,121,115,117,4,0,0,0,112,97,116,104,117,20,0,0, + 0,95,112,97,116,104,95,105,109,112,111,114,116,101,114,95, + 99,97,99,104,101,117,11,0,0,0,73,109,112,111,114,116, + 69,114,114,111,114,117,11,0,0,0,102,105,110,100,95,109, + 111,100,117,108,101,117,4,0,0,0,78,111,110,101,40,6, + 0,0,0,117,3,0,0,0,99,108,115,117,8,0,0,0, + 102,117,108,108,110,97,109,101,117,4,0,0,0,112,97,116, + 104,117,5,0,0,0,101,110,116,114,121,117,6,0,0,0, + 102,105,110,100,101,114,117,6,0,0,0,108,111,97,100,101, + 114,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,11,0, + 0,0,102,105,110,100,95,109,111,100,117,108,101,230,2,0, + 0,115,24,0,0,0,0,4,6,1,12,1,13,1,3,1, + 19,1,13,1,8,1,6,1,15,1,6,1,11,2,117,22, + 0,0,0,80,97,116,104,70,105,110,100,101,114,46,102,105, + 110,100,95,109,111,100,117,108,101,78,40,9,0,0,0,117, + 8,0,0,0,95,95,110,97,109,101,95,95,117,10,0,0, + 0,95,95,109,111,100,117,108,101,95,95,117,12,0,0,0, + 95,95,113,117,97,108,110,97,109,101,95,95,117,7,0,0, + 0,95,95,100,111,99,95,95,117,11,0,0,0,99,108,97, + 115,115,109,101,116,104,111,100,117,4,0,0,0,78,111,110, + 101,117,11,0,0,0,95,112,97,116,104,95,104,111,111,107, + 115,117,20,0,0,0,95,112,97,116,104,95,105,109,112,111, + 114,116,101,114,95,99,97,99,104,101,117,11,0,0,0,102, + 105,110,100,95,109,111,100,117,108,101,40,1,0,0,0,117, + 10,0,0,0,95,95,108,111,99,97,108,115,95,95,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,80, + 97,116,104,70,105,110,100,101,114,181,2,0,0,115,14,0, + 0,0,16,2,6,2,3,1,18,17,3,1,18,26,3,1, + 117,10,0,0,0,80,97,116,104,70,105,110,100,101,114,99, + 1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, + 66,0,0,0,115,74,0,0,0,124,0,0,69,101,0,0, + 90,1,0,100,0,0,90,2,0,100,1,0,90,3,0,100, + 2,0,100,3,0,132,0,0,90,4,0,100,4,0,100,5, + 0,132,0,0,90,5,0,100,6,0,100,7,0,132,0,0, + 90,6,0,100,8,0,100,9,0,132,0,0,90,7,0,100, + 10,0,83,40,11,0,0,0,117,11,0,0,0,95,70,105, + 108,101,70,105,110,100,101,114,117,171,0,0,0,70,105,108, + 101,45,98,97,115,101,100,32,102,105,110,100,101,114,46,10, + 10,32,32,32,32,67,111,110,115,116,114,117,99,116,111,114, + 32,116,97,107,101,115,32,97,32,108,105,115,116,32,111,102, + 32,111,98,106,101,99,116,115,32,100,101,116,97,105,108,105, + 110,103,32,119,104,97,116,32,102,105,108,101,32,101,120,116, + 101,110,115,105,111,110,115,32,116,104,101,105,114,10,32,32, + 32,32,108,111,97,100,101,114,32,115,117,112,112,111,114,116, + 115,32,97,108,111,110,103,32,119,105,116,104,32,119,104,101, + 116,104,101,114,32,105,116,32,99,97,110,32,98,101,32,117, + 115,101,100,32,102,111,114,32,97,32,112,97,99,107,97,103, + 101,46,10,10,32,32,32,32,99,2,0,0,0,0,0,0, + 0,5,0,0,0,5,0,0,0,7,0,0,0,115,181,0, + 0,0,103,0,0,125,3,0,103,0,0,125,4,0,120,96, + 0,124,2,0,68,93,88,0,137,0,0,124,4,0,106,0, + 0,135,0,0,102,1,0,100,1,0,100,2,0,134,0,0, + 136,0,0,106,1,0,68,131,1,0,131,1,0,1,136,0, + 0,106,2,0,114,19,0,124,3,0,106,0,0,135,0,0, + 102,1,0,100,3,0,100,2,0,134,0,0,136,0,0,106, + 1,0,68,131,1,0,131,1,0,1,113,19,0,113,19,0, + 87,124,3,0,124,0,0,95,3,0,124,4,0,124,0,0, + 95,4,0,124,1,0,112,138,0,100,4,0,124,0,0,95, + 5,0,100,7,0,124,0,0,95,6,0,116,7,0,131,0, + 0,124,0,0,95,8,0,116,7,0,131,0,0,124,0,0, + 95,9,0,100,6,0,83,40,8,0,0,0,117,31,0,0, + 0,73,110,105,116,105,97,108,105,122,101,32,119,105,116,104, + 32,102,105,110,100,101,114,32,100,101,116,97,105,108,115,46, + 99,1,0,0,0,0,0,0,0,2,0,0,0,3,0,0, + 0,51,0,0,0,115,30,0,0,0,124,0,0,93,20,0, + 125,1,0,124,1,0,136,0,0,106,0,0,102,2,0,86, + 1,113,3,0,100,0,0,83,40,1,0,0,0,78,40,1, + 0,0,0,117,6,0,0,0,108,111,97,100,101,114,40,2, + 0,0,0,117,2,0,0,0,46,48,117,6,0,0,0,115, + 117,102,102,105,120,40,1,0,0,0,117,6,0,0,0,100, + 101,116,97,105,108,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,9,0,0, + 0,60,103,101,110,101,120,112,114,62,7,3,0,0,115,2, + 0,0,0,6,0,117,39,0,0,0,95,70,105,108,101,70, + 105,110,100,101,114,46,95,95,105,110,105,116,95,95,46,60, + 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, + 62,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,51,0,0,0,115,30,0,0,0,124,0,0,93,20, + 0,125,1,0,124,1,0,136,0,0,106,0,0,102,2,0, + 86,1,113,3,0,100,0,0,83,40,1,0,0,0,78,40, + 1,0,0,0,117,6,0,0,0,108,111,97,100,101,114,40, + 2,0,0,0,117,2,0,0,0,46,48,117,6,0,0,0, + 115,117,102,102,105,120,40,1,0,0,0,117,6,0,0,0, + 100,101,116,97,105,108,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,9,0, + 0,0,60,103,101,110,101,120,112,114,62,9,3,0,0,115, + 2,0,0,0,6,1,117,1,0,0,0,46,105,1,0,0, + 0,78,105,255,255,255,255,40,10,0,0,0,117,6,0,0, + 0,101,120,116,101,110,100,117,8,0,0,0,115,117,102,102, + 105,120,101,115,117,17,0,0,0,115,117,112,112,111,114,116, + 115,95,112,97,99,107,97,103,101,115,117,8,0,0,0,112, + 97,99,107,97,103,101,115,117,7,0,0,0,109,111,100,117, + 108,101,115,117,4,0,0,0,112,97,116,104,117,11,0,0, + 0,95,112,97,116,104,95,109,116,105,109,101,117,3,0,0, + 0,115,101,116,117,11,0,0,0,95,112,97,116,104,95,99, + 97,99,104,101,117,19,0,0,0,95,114,101,108,97,120,101, + 100,95,112,97,116,104,95,99,97,99,104,101,40,5,0,0, + 0,117,4,0,0,0,115,101,108,102,117,4,0,0,0,112, + 97,116,104,117,7,0,0,0,100,101,116,97,105,108,115,117, + 8,0,0,0,112,97,99,107,97,103,101,115,117,7,0,0, + 0,109,111,100,117,108,101,115,40,0,0,0,0,40,1,0, + 0,0,117,6,0,0,0,100,101,116,97,105,108,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 8,0,0,0,95,95,105,110,105,116,95,95,2,3,0,0, + 115,26,0,0,0,0,2,6,1,6,1,13,1,35,1,9, + 1,21,1,21,1,9,1,9,2,15,1,9,1,12,1,117, + 20,0,0,0,95,70,105,108,101,70,105,110,100,101,114,46, + 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, + 0,1,0,0,0,2,0,0,0,67,0,0,0,115,13,0, + 0,0,100,3,0,124,0,0,95,0,0,100,2,0,83,40, + 4,0,0,0,117,31,0,0,0,73,110,118,97,108,105,100, + 97,116,101,32,116,104,101,32,100,105,114,101,99,116,111,114, + 121,32,109,116,105,109,101,46,105,1,0,0,0,78,105,255, + 255,255,255,40,1,0,0,0,117,11,0,0,0,95,112,97, + 116,104,95,109,116,105,109,101,40,1,0,0,0,117,4,0, + 0,0,115,101,108,102,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,17,0,0,0,105,110,118,97,108,105,100,97,116, + 101,95,99,97,99,104,101,115,19,3,0,0,115,2,0,0, + 0,0,2,117,29,0,0,0,95,70,105,108,101,70,105,110, + 100,101,114,46,105,110,118,97,108,105,100,97,116,101,95,99, + 97,99,104,101,115,99,2,0,0,0,0,0,0,0,12,0, + 0,0,13,0,0,0,67,0,0,0,115,151,1,0,0,124, + 1,0,106,0,0,100,1,0,131,1,0,100,2,0,25,125, + 2,0,121,25,0,116,1,0,106,2,0,124,0,0,106,3, + 0,131,1,0,106,4,0,125,3,0,87,110,24,0,4,116, + 5,0,107,10,0,114,70,0,1,1,1,100,6,0,125,3, + 0,89,110,1,0,88,124,3,0,124,0,0,106,6,0,107, + 3,0,114,108,0,124,0,0,106,7,0,131,0,0,1,124, + 3,0,124,0,0,95,6,0,110,0,0,116,8,0,131,0, + 0,114,141,0,124,0,0,106,9,0,125,4,0,124,2,0, + 106,10,0,131,0,0,125,5,0,110,15,0,124,0,0,106, + 11,0,125,4,0,124,2,0,125,5,0,124,5,0,124,4, + 0,107,6,0,114,55,1,116,12,0,124,0,0,106,3,0, + 124,2,0,131,2,0,125,6,0,116,13,0,124,6,0,131, + 1,0,114,55,1,120,107,0,124,0,0,106,14,0,68,93, + 62,0,92,2,0,125,7,0,125,8,0,100,4,0,124,7, + 0,23,125,9,0,116,12,0,124,6,0,124,9,0,131,2, + 0,125,10,0,116,15,0,124,10,0,131,1,0,114,208,0, + 124,8,0,124,1,0,124,10,0,131,2,0,83,113,208,0, + 87,100,5,0,125,11,0,116,16,0,106,17,0,124,11,0, + 106,18,0,124,6,0,131,1,0,116,19,0,131,2,0,1, + 113,55,1,110,0,0,120,89,0,124,0,0,106,20,0,68, + 93,78,0,92,2,0,125,7,0,125,8,0,124,5,0,124, + 7,0,23,124,4,0,107,6,0,114,65,1,116,12,0,124, + 0,0,106,3,0,124,2,0,124,7,0,23,131,2,0,125, + 10,0,116,15,0,124,10,0,131,1,0,114,143,1,124,8, + 0,124,1,0,124,10,0,131,2,0,83,113,65,1,113,65, + 1,87,100,7,0,83,40,8,0,0,0,117,46,0,0,0, + 84,114,121,32,116,111,32,102,105,110,100,32,97,32,108,111, + 97,100,101,114,32,102,111,114,32,116,104,101,32,115,112,101, + 99,105,102,105,101,100,32,109,111,100,117,108,101,46,117,1, + 0,0,0,46,105,2,0,0,0,105,1,0,0,0,117,8, + 0,0,0,95,95,105,110,105,116,95,95,117,44,0,0,0, + 78,111,116,32,105,109,112,111,114,116,105,110,103,32,100,105, + 114,101,99,116,111,114,121,32,123,125,58,32,109,105,115,115, + 105,110,103,32,95,95,105,110,105,116,95,95,105,255,255,255, + 255,78,40,22,0,0,0,117,10,0,0,0,114,112,97,114, + 116,105,116,105,111,110,117,3,0,0,0,95,111,115,117,4, + 0,0,0,115,116,97,116,117,4,0,0,0,112,97,116,104, + 117,8,0,0,0,115,116,95,109,116,105,109,101,117,7,0, + 0,0,79,83,69,114,114,111,114,117,11,0,0,0,95,112, + 97,116,104,95,109,116,105,109,101,117,11,0,0,0,95,102, + 105,108,108,95,99,97,99,104,101,117,11,0,0,0,95,114, + 101,108,97,120,95,99,97,115,101,117,19,0,0,0,95,114, + 101,108,97,120,101,100,95,112,97,116,104,95,99,97,99,104, + 101,117,5,0,0,0,108,111,119,101,114,117,11,0,0,0, + 95,112,97,116,104,95,99,97,99,104,101,117,10,0,0,0, + 95,112,97,116,104,95,106,111,105,110,117,11,0,0,0,95, + 112,97,116,104,95,105,115,100,105,114,117,8,0,0,0,112, + 97,99,107,97,103,101,115,117,12,0,0,0,95,112,97,116, + 104,95,105,115,102,105,108,101,117,9,0,0,0,95,119,97, + 114,110,105,110,103,115,117,4,0,0,0,119,97,114,110,117, + 6,0,0,0,102,111,114,109,97,116,117,13,0,0,0,73, + 109,112,111,114,116,87,97,114,110,105,110,103,117,7,0,0, + 0,109,111,100,117,108,101,115,117,4,0,0,0,78,111,110, + 101,40,12,0,0,0,117,4,0,0,0,115,101,108,102,117, + 8,0,0,0,102,117,108,108,110,97,109,101,117,11,0,0, + 0,116,97,105,108,95,109,111,100,117,108,101,117,5,0,0, + 0,109,116,105,109,101,117,5,0,0,0,99,97,99,104,101, + 117,12,0,0,0,99,97,99,104,101,95,109,111,100,117,108, + 101,117,9,0,0,0,98,97,115,101,95,112,97,116,104,117, + 6,0,0,0,115,117,102,102,105,120,117,6,0,0,0,108, + 111,97,100,101,114,117,13,0,0,0,105,110,105,116,95,102, + 105,108,101,110,97,109,101,117,9,0,0,0,102,117,108,108, + 95,112,97,116,104,117,3,0,0,0,109,115,103,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,11,0,0,0,102,105, + 110,100,95,109,111,100,117,108,101,23,3,0,0,115,58,0, + 0,0,0,2,19,1,3,1,25,1,13,1,11,1,15,1, + 10,1,12,2,9,1,9,1,15,2,9,1,6,1,12,1, + 18,1,12,1,22,1,10,1,15,1,12,1,17,2,6,1, + 31,1,22,1,16,1,22,1,12,1,20,1,117,23,0,0, + 0,95,70,105,108,101,70,105,110,100,101,114,46,102,105,110, + 100,95,109,111,100,117,108,101,99,1,0,0,0,0,0,0, + 0,3,0,0,0,3,0,0,0,67,0,0,0,115,71,0, + 0,0,124,0,0,106,0,0,125,1,0,116,1,0,106,2, + 0,124,1,0,131,1,0,125,2,0,116,3,0,124,2,0, + 131,1,0,124,0,0,95,4,0,116,3,0,100,1,0,100, + 2,0,132,0,0,124,2,0,68,131,1,0,131,1,0,124, + 0,0,95,5,0,100,3,0,83,40,4,0,0,0,117,68, + 0,0,0,70,105,108,108,32,116,104,101,32,99,97,99,104, + 101,32,111,102,32,112,111,116,101,110,116,105,97,108,32,109, + 111,100,117,108,101,115,32,97,110,100,32,112,97,99,107,97, + 103,101,115,32,102,111,114,32,116,104,105,115,32,100,105,114, + 101,99,116,111,114,121,46,99,1,0,0,0,0,0,0,0, + 2,0,0,0,2,0,0,0,115,0,0,0,115,27,0,0, + 0,124,0,0,93,17,0,125,1,0,124,1,0,106,0,0, + 131,0,0,86,1,113,3,0,100,0,0,83,40,1,0,0, + 0,78,40,1,0,0,0,117,5,0,0,0,108,111,119,101, + 114,40,2,0,0,0,117,2,0,0,0,46,48,117,2,0, + 0,0,102,110,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,9,0,0,0,60,103,101,110,101,120,112,114,62,65,3, + 0,0,115,2,0,0,0,6,0,117,42,0,0,0,95,70, + 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, + 99,97,99,104,101,46,60,108,111,99,97,108,115,62,46,60, + 103,101,110,101,120,112,114,62,78,40,6,0,0,0,117,4, + 0,0,0,112,97,116,104,117,3,0,0,0,95,111,115,117, + 7,0,0,0,108,105,115,116,100,105,114,117,3,0,0,0, + 115,101,116,117,11,0,0,0,95,112,97,116,104,95,99,97, + 99,104,101,117,19,0,0,0,95,114,101,108,97,120,101,100, + 95,112,97,116,104,95,99,97,99,104,101,40,3,0,0,0, + 117,4,0,0,0,115,101,108,102,117,4,0,0,0,112,97, + 116,104,117,8,0,0,0,99,111,110,116,101,110,116,115,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, + 95,102,105,108,108,95,99,97,99,104,101,58,3,0,0,115, + 8,0,0,0,0,2,9,1,15,3,15,1,117,23,0,0, + 0,95,70,105,108,101,70,105,110,100,101,114,46,95,102,105, + 108,108,95,99,97,99,104,101,78,40,8,0,0,0,117,8, + 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, + 95,95,109,111,100,117,108,101,95,95,117,12,0,0,0,95, + 95,113,117,97,108,110,97,109,101,95,95,117,7,0,0,0, + 95,95,100,111,99,95,95,117,8,0,0,0,95,95,105,110, + 105,116,95,95,117,17,0,0,0,105,110,118,97,108,105,100, + 97,116,101,95,99,97,99,104,101,115,117,11,0,0,0,102, + 105,110,100,95,109,111,100,117,108,101,117,11,0,0,0,95, + 102,105,108,108,95,99,97,99,104,101,40,1,0,0,0,117, + 10,0,0,0,95,95,108,111,99,97,108,115,95,95,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,11,0,0,0,95, + 70,105,108,101,70,105,110,100,101,114,249,2,0,0,115,10, + 0,0,0,16,7,6,2,12,17,12,4,12,35,117,11,0, + 0,0,95,70,105,108,101,70,105,110,100,101,114,99,1,0, + 0,0,0,0,0,0,1,0,0,0,2,0,0,0,66,0, + 0,0,115,44,0,0,0,124,0,0,69,101,0,0,90,1, + 0,100,0,0,90,2,0,101,3,0,90,4,0,100,4,0, + 90,6,0,100,1,0,100,2,0,132,0,0,90,7,0,100, + 3,0,83,40,5,0,0,0,117,20,0,0,0,95,83,111, + 117,114,99,101,70,105,110,100,101,114,68,101,116,97,105,108, + 115,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, + 0,0,67,0,0,0,115,22,0,0,0,116,0,0,116,1, + 0,106,2,0,131,1,0,124,0,0,95,3,0,100,0,0, + 83,40,1,0,0,0,78,40,4,0,0,0,117,12,0,0, + 0,95,115,117,102,102,105,120,95,108,105,115,116,117,3,0, + 0,0,105,109,112,117,9,0,0,0,80,89,95,83,79,85, + 82,67,69,117,8,0,0,0,115,117,102,102,105,120,101,115, + 40,1,0,0,0,117,4,0,0,0,115,101,108,102,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,8,0,0,0,95, + 95,105,110,105,116,95,95,73,3,0,0,115,2,0,0,0, + 0,1,117,29,0,0,0,95,83,111,117,114,99,101,70,105, + 110,100,101,114,68,101,116,97,105,108,115,46,95,95,105,110, + 105,116,95,95,78,84,40,8,0,0,0,117,8,0,0,0, + 95,95,110,97,109,101,95,95,117,10,0,0,0,95,95,109, + 111,100,117,108,101,95,95,117,12,0,0,0,95,95,113,117, + 97,108,110,97,109,101,95,95,117,17,0,0,0,95,83,111, + 117,114,99,101,70,105,108,101,76,111,97,100,101,114,117,6, + 0,0,0,108,111,97,100,101,114,117,4,0,0,0,84,114, + 117,101,117,17,0,0,0,115,117,112,112,111,114,116,115,95, + 112,97,99,107,97,103,101,115,117,8,0,0,0,95,95,105, + 110,105,116,95,95,40,1,0,0,0,117,10,0,0,0,95, + 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,20,0,0,0,95,83,111,117,114,99, + 101,70,105,110,100,101,114,68,101,116,97,105,108,115,68,3, + 0,0,115,6,0,0,0,16,2,6,1,6,2,117,20,0, + 0,0,95,83,111,117,114,99,101,70,105,110,100,101,114,68, + 101,116,97,105,108,115,99,1,0,0,0,0,0,0,0,1, + 0,0,0,2,0,0,0,66,0,0,0,115,44,0,0,0, + 124,0,0,69,101,0,0,90,1,0,100,0,0,90,2,0, + 101,3,0,90,4,0,100,4,0,90,6,0,100,1,0,100, + 2,0,132,0,0,90,7,0,100,3,0,83,40,5,0,0, + 0,117,24,0,0,0,95,83,111,117,114,99,101,108,101,115, + 115,70,105,110,100,101,114,68,101,116,97,105,108,115,99,1, + 0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,67, + 0,0,0,115,22,0,0,0,116,0,0,116,1,0,106,2, + 0,131,1,0,124,0,0,95,3,0,100,0,0,83,40,1, + 0,0,0,78,40,4,0,0,0,117,12,0,0,0,95,115, + 117,102,102,105,120,95,108,105,115,116,117,3,0,0,0,105, + 109,112,117,11,0,0,0,80,89,95,67,79,77,80,73,76, + 69,68,117,8,0,0,0,115,117,102,102,105,120,101,115,40, + 1,0,0,0,117,4,0,0,0,115,101,108,102,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,8,0,0,0,95,95, + 105,110,105,116,95,95,81,3,0,0,115,2,0,0,0,0, + 1,117,33,0,0,0,95,83,111,117,114,99,101,108,101,115, + 115,70,105,110,100,101,114,68,101,116,97,105,108,115,46,95, + 95,105,110,105,116,95,95,78,84,40,8,0,0,0,117,8, + 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, + 95,95,109,111,100,117,108,101,95,95,117,12,0,0,0,95, + 95,113,117,97,108,110,97,109,101,95,95,117,21,0,0,0, + 95,83,111,117,114,99,101,108,101,115,115,70,105,108,101,76, + 111,97,100,101,114,117,6,0,0,0,108,111,97,100,101,114, + 117,4,0,0,0,84,114,117,101,117,17,0,0,0,115,117, + 112,112,111,114,116,115,95,112,97,99,107,97,103,101,115,117, + 8,0,0,0,95,95,105,110,105,116,95,95,40,1,0,0, + 0,117,10,0,0,0,95,95,108,111,99,97,108,115,95,95, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,24,0,0, + 0,95,83,111,117,114,99,101,108,101,115,115,70,105,110,100, + 101,114,68,101,116,97,105,108,115,76,3,0,0,115,6,0, + 0,0,16,2,6,1,6,2,117,24,0,0,0,95,83,111, + 117,114,99,101,108,101,115,115,70,105,110,100,101,114,68,101, + 116,97,105,108,115,99,1,0,0,0,0,0,0,0,1,0, + 0,0,2,0,0,0,66,0,0,0,115,44,0,0,0,124, + 0,0,69,101,0,0,90,1,0,100,0,0,90,2,0,101, + 3,0,90,4,0,100,4,0,90,6,0,100,1,0,100,2, + 0,132,0,0,90,7,0,100,3,0,83,40,5,0,0,0, + 117,23,0,0,0,95,69,120,116,101,110,115,105,111,110,70, + 105,110,100,101,114,68,101,116,97,105,108,115,99,1,0,0, + 0,0,0,0,0,1,0,0,0,2,0,0,0,67,0,0, + 0,115,22,0,0,0,116,0,0,116,1,0,106,2,0,131, + 1,0,124,0,0,95,3,0,100,0,0,83,40,1,0,0, + 0,78,40,4,0,0,0,117,12,0,0,0,95,115,117,102, + 102,105,120,95,108,105,115,116,117,3,0,0,0,105,109,112, + 117,11,0,0,0,67,95,69,88,84,69,78,83,73,79,78, + 117,8,0,0,0,115,117,102,102,105,120,101,115,40,1,0, + 0,0,117,4,0,0,0,115,101,108,102,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,8,0,0,0,95,95,105,110, + 105,116,95,95,90,3,0,0,115,2,0,0,0,0,1,117, + 32,0,0,0,95,69,120,116,101,110,115,105,111,110,70,105, + 110,100,101,114,68,101,116,97,105,108,115,46,95,95,105,110, + 105,116,95,95,78,70,40,8,0,0,0,117,8,0,0,0, + 95,95,110,97,109,101,95,95,117,10,0,0,0,95,95,109, + 111,100,117,108,101,95,95,117,12,0,0,0,95,95,113,117, + 97,108,110,97,109,101,95,95,117,20,0,0,0,95,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,117,6,0,0,0,108,111,97,100,101,114,117,5,0,0, + 0,70,97,108,115,101,117,17,0,0,0,115,117,112,112,111, + 114,116,115,95,112,97,99,107,97,103,101,115,117,8,0,0, + 0,95,95,105,110,105,116,95,95,40,1,0,0,0,117,10, + 0,0,0,95,95,108,111,99,97,108,115,95,95,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,23,0,0,0,95,69, + 120,116,101,110,115,105,111,110,70,105,110,100,101,114,68,101, + 116,97,105,108,115,85,3,0,0,115,6,0,0,0,16,2, + 6,1,6,2,117,23,0,0,0,95,69,120,116,101,110,115, + 105,111,110,70,105,110,100,101,114,68,101,116,97,105,108,115, + 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, + 0,67,0,0,0,115,62,0,0,0,116,0,0,124,0,0, + 131,1,0,114,40,0,116,1,0,124,0,0,116,2,0,131, + 0,0,116,3,0,131,0,0,116,4,0,131,0,0,131,4, + 0,83,116,5,0,100,1,0,100,2,0,124,0,0,131,1, + 1,130,1,0,100,3,0,83,40,4,0,0,0,117,55,0, + 0,0,73,102,32,116,104,101,32,112,97,116,104,32,105,115, + 32,97,32,100,105,114,101,99,116,111,114,121,44,32,114,101, + 116,117,114,110,32,97,32,102,105,108,101,45,98,97,115,101, + 100,32,102,105,110,100,101,114,46,117,30,0,0,0,111,110, + 108,121,32,100,105,114,101,99,116,111,114,105,101,115,32,97, + 114,101,32,115,117,112,112,111,114,116,101,100,117,4,0,0, + 0,112,97,116,104,78,40,6,0,0,0,117,11,0,0,0, + 95,112,97,116,104,95,105,115,100,105,114,117,11,0,0,0, + 95,70,105,108,101,70,105,110,100,101,114,117,23,0,0,0, + 95,69,120,116,101,110,115,105,111,110,70,105,110,100,101,114, + 68,101,116,97,105,108,115,117,20,0,0,0,95,83,111,117, + 114,99,101,70,105,110,100,101,114,68,101,116,97,105,108,115, + 117,24,0,0,0,95,83,111,117,114,99,101,108,101,115,115, + 70,105,110,100,101,114,68,101,116,97,105,108,115,117,11,0, + 0,0,73,109,112,111,114,116,69,114,114,111,114,40,1,0, + 0,0,117,4,0,0,0,112,97,116,104,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,15,0,0,0,95,102,105,108, + 101,95,112,97,116,104,95,104,111,111,107,96,3,0,0,115, + 10,0,0,0,0,2,12,1,12,1,6,1,10,2,117,15, + 0,0,0,95,102,105,108,101,95,112,97,116,104,95,104,111, + 111,107,99,1,0,0,0,0,0,0,0,1,0,0,0,4, + 0,0,0,2,0,0,0,115,74,0,0,0,124,0,0,69, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, + 3,0,101,4,0,135,0,0,102,1,0,100,2,0,100,3, + 0,134,0,0,131,1,0,90,5,0,101,4,0,135,0,0, + 102,1,0,100,4,0,100,5,0,134,0,0,131,1,0,90, + 6,0,135,0,0,83,40,6,0,0,0,117,18,0,0,0, + 95,68,101,102,97,117,108,116,80,97,116,104,70,105,110,100, + 101,114,117,77,0,0,0,83,117,98,99,108,97,115,115,32, + 111,102,32,80,97,116,104,70,105,110,100,101,114,32,116,104, + 97,116,32,105,109,112,108,101,109,101,110,116,115,32,105,109, + 112,108,105,99,105,116,32,115,101,109,97,110,116,105,99,115, + 32,102,111,114,10,32,32,32,32,95,95,105,109,112,111,114, + 116,95,95,46,99,2,0,0,0,0,0,0,0,3,0,0, + 0,11,0,0,0,3,0,0,0,115,79,0,0,0,121,20, + 0,116,0,0,131,0,0,106,1,0,124,1,0,131,1,0, + 83,87,110,52,0,4,116,2,0,107,10,0,114,74,0,1, + 1,1,116,3,0,116,4,0,106,5,0,103,2,0,125,2, + 0,116,0,0,131,0,0,106,1,0,124,1,0,124,2,0, + 131,2,0,83,89,110,1,0,88,100,1,0,83,40,2,0, + 0,0,117,53,0,0,0,83,101,97,114,99,104,32,115,121, + 115,46,112,97,116,104,95,104,111,111,107,115,32,97,115,32, + 119,101,108,108,32,97,115,32,105,109,112,108,105,99,105,116, + 32,112,97,116,104,32,104,111,111,107,115,46,78,40,6,0, + 0,0,117,5,0,0,0,115,117,112,101,114,117,11,0,0, + 0,95,112,97,116,104,95,104,111,111,107,115,117,11,0,0, + 0,73,109,112,111,114,116,69,114,114,111,114,117,18,0,0, + 0,95,68,69,70,65,85,76,84,95,80,65,84,72,95,72, + 79,79,75,117,3,0,0,0,105,109,112,117,12,0,0,0, + 78,117,108,108,73,109,112,111,114,116,101,114,40,3,0,0, + 0,117,3,0,0,0,99,108,115,117,4,0,0,0,112,97, + 116,104,117,14,0,0,0,105,109,112,108,105,99,105,116,95, + 104,111,111,107,115,40,1,0,0,0,117,10,0,0,0,64, + 95,95,99,108,97,115,115,95,95,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,11,0,0,0,95,112,97,116,104,95,104,111,111,107,115, + 113,3,0,0,115,10,0,0,0,0,3,3,1,20,1,13, + 1,15,1,117,30,0,0,0,95,68,101,102,97,117,108,116, + 80,97,116,104,70,105,110,100,101,114,46,95,112,97,116,104, + 95,104,111,111,107,115,99,2,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,3,0,0,0,115,19,0,0,0, + 116,0,0,131,0,0,106,1,0,124,1,0,116,2,0,131, + 2,0,83,40,1,0,0,0,117,81,0,0,0,85,115,101, + 32,116,104,101,32,100,101,102,97,117,108,116,32,112,97,116, + 104,32,104,111,111,107,32,119,104,101,110,32,78,111,110,101, + 32,105,115,32,115,116,111,114,101,100,32,105,110,10,32,32, + 32,32,32,32,32,32,115,121,115,46,112,97,116,104,95,105, + 109,112,111,114,116,101,114,95,99,97,99,104,101,46,40,3, + 0,0,0,117,5,0,0,0,115,117,112,101,114,117,20,0, + 0,0,95,112,97,116,104,95,105,109,112,111,114,116,101,114, + 95,99,97,99,104,101,117,18,0,0,0,95,68,69,70,65, + 85,76,84,95,80,65,84,72,95,72,79,79,75,40,2,0, + 0,0,117,3,0,0,0,99,108,115,117,4,0,0,0,112, + 97,116,104,40,1,0,0,0,117,10,0,0,0,64,95,95, + 99,108,97,115,115,95,95,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,20, + 0,0,0,95,112,97,116,104,95,105,109,112,111,114,116,101, + 114,95,99,97,99,104,101,122,3,0,0,115,2,0,0,0, + 0,4,117,39,0,0,0,95,68,101,102,97,117,108,116,80, + 97,116,104,70,105,110,100,101,114,46,95,112,97,116,104,95, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,40,7, + 0,0,0,117,8,0,0,0,95,95,110,97,109,101,95,95, + 117,10,0,0,0,95,95,109,111,100,117,108,101,95,95,117, + 12,0,0,0,95,95,113,117,97,108,110,97,109,101,95,95, + 117,7,0,0,0,95,95,100,111,99,95,95,117,11,0,0, + 0,99,108,97,115,115,109,101,116,104,111,100,117,11,0,0, + 0,95,112,97,116,104,95,104,111,111,107,115,117,20,0,0, + 0,95,112,97,116,104,95,105,109,112,111,114,116,101,114,95, + 99,97,99,104,101,40,1,0,0,0,117,10,0,0,0,95, + 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,1, + 0,0,0,117,10,0,0,0,64,95,95,99,108,97,115,115, + 95,95,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,18,0,0,0,95,68,101,102,97,117,108, + 116,80,97,116,104,70,105,110,100,101,114,108,3,0,0,115, + 6,0,0,0,16,3,6,2,24,9,117,18,0,0,0,95, + 68,101,102,97,117,108,116,80,97,116,104,70,105,110,100,101, + 114,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, + 0,0,66,0,0,0,115,50,0,0,0,124,0,0,69,101, + 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, + 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, + 100,5,0,132,0,0,90,5,0,100,6,0,83,40,7,0, + 0,0,117,18,0,0,0,95,73,109,112,111,114,116,76,111, + 99,107,67,111,110,116,101,120,116,117,36,0,0,0,67,111, + 110,116,101,120,116,32,109,97,110,97,103,101,114,32,102,111, + 114,32,116,104,101,32,105,109,112,111,114,116,32,108,111,99, + 107,46,99,1,0,0,0,0,0,0,0,1,0,0,0,1, + 0,0,0,67,0,0,0,115,14,0,0,0,116,0,0,106, + 1,0,131,0,0,1,100,1,0,83,40,2,0,0,0,117, + 24,0,0,0,65,99,113,117,105,114,101,32,116,104,101,32, + 105,109,112,111,114,116,32,108,111,99,107,46,78,40,2,0, + 0,0,117,3,0,0,0,105,109,112,117,12,0,0,0,97, + 99,113,117,105,114,101,95,108,111,99,107,40,1,0,0,0, + 117,4,0,0,0,115,101,108,102,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,9,0,0,0,95,95,101,110,116,101, + 114,95,95,133,3,0,0,115,2,0,0,0,0,2,117,28, + 0,0,0,95,73,109,112,111,114,116,76,111,99,107,67,111, + 110,116,101,120,116,46,95,95,101,110,116,101,114,95,95,99, + 4,0,0,0,0,0,0,0,4,0,0,0,1,0,0,0, + 67,0,0,0,115,14,0,0,0,116,0,0,106,1,0,131, + 0,0,1,100,1,0,83,40,2,0,0,0,117,60,0,0, + 0,82,101,108,101,97,115,101,32,116,104,101,32,105,109,112, + 111,114,116,32,108,111,99,107,32,114,101,103,97,114,100,108, + 101,115,115,32,111,102,32,97,110,121,32,114,97,105,115,101, + 100,32,101,120,99,101,112,116,105,111,110,115,46,78,40,2, + 0,0,0,117,3,0,0,0,105,109,112,117,12,0,0,0, + 114,101,108,101,97,115,101,95,108,111,99,107,40,4,0,0, + 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,101, + 120,99,95,116,121,112,101,117,9,0,0,0,101,120,99,95, + 118,97,108,117,101,117,13,0,0,0,101,120,99,95,116,114, + 97,99,101,98,97,99,107,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,8,0,0,0,95,95,101,120,105,116,95,95, + 137,3,0,0,115,2,0,0,0,0,2,117,27,0,0,0, + 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, + 120,116,46,95,95,101,120,105,116,95,95,78,40,6,0,0, + 0,117,8,0,0,0,95,95,110,97,109,101,95,95,117,10, + 0,0,0,95,95,109,111,100,117,108,101,95,95,117,12,0, + 0,0,95,95,113,117,97,108,110,97,109,101,95,95,117,7, + 0,0,0,95,95,100,111,99,95,95,117,9,0,0,0,95, + 95,101,110,116,101,114,95,95,117,8,0,0,0,95,95,101, + 120,105,116,95,95,40,1,0,0,0,117,10,0,0,0,95, + 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,18,0,0,0,95,73,109,112,111,114, + 116,76,111,99,107,67,111,110,116,101,120,116,129,3,0,0, + 115,6,0,0,0,16,2,6,2,12,4,117,18,0,0,0, + 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, + 120,116,99,3,0,0,0,0,0,0,0,5,0,0,0,4, + 0,0,0,67,0,0,0,115,91,0,0,0,124,1,0,106, + 0,0,100,1,0,124,2,0,100,2,0,24,131,2,0,125, + 3,0,116,1,0,124,3,0,131,1,0,124,2,0,107,0, + 0,114,55,0,116,2,0,100,3,0,131,1,0,130,1,0, + 110,0,0,124,3,0,100,4,0,25,125,4,0,124,0,0, + 114,87,0,100,5,0,106,3,0,124,4,0,124,0,0,131, + 2,0,83,124,4,0,83,40,6,0,0,0,117,50,0,0, + 0,82,101,115,111,108,118,101,32,97,32,114,101,108,97,116, + 105,118,101,32,109,111,100,117,108,101,32,110,97,109,101,32, + 116,111,32,97,110,32,97,98,115,111,108,117,116,101,32,111, + 110,101,46,117,1,0,0,0,46,105,1,0,0,0,117,50, + 0,0,0,97,116,116,101,109,112,116,101,100,32,114,101,108, + 97,116,105,118,101,32,105,109,112,111,114,116,32,98,101,121, + 111,110,100,32,116,111,112,45,108,101,118,101,108,32,112,97, + 99,107,97,103,101,105,0,0,0,0,117,7,0,0,0,123, + 48,125,46,123,49,125,40,4,0,0,0,117,6,0,0,0, + 114,115,112,108,105,116,117,3,0,0,0,108,101,110,117,10, + 0,0,0,86,97,108,117,101,69,114,114,111,114,117,6,0, + 0,0,102,111,114,109,97,116,40,5,0,0,0,117,4,0, + 0,0,110,97,109,101,117,7,0,0,0,112,97,99,107,97, + 103,101,117,5,0,0,0,108,101,118,101,108,117,4,0,0, + 0,98,105,116,115,117,4,0,0,0,98,97,115,101,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,13,0,0,0,95, + 114,101,115,111,108,118,101,95,110,97,109,101,142,3,0,0, + 115,10,0,0,0,0,2,22,1,18,1,15,1,10,1,117, + 13,0,0,0,95,114,101,115,111,108,118,101,95,110,97,109, + 101,99,2,0,0,0,0,0,0,0,5,0,0,0,4,0, + 0,0,67,0,0,0,115,104,0,0,0,116,0,0,106,1, + 0,116,2,0,23,125,2,0,120,84,0,124,2,0,68,93, + 72,0,125,3,0,124,3,0,106,3,0,124,0,0,124,1, + 0,131,2,0,125,4,0,124,4,0,100,1,0,107,9,0, + 114,20,0,124,0,0,116,0,0,106,5,0,107,7,0,114, + 75,0,124,4,0,83,116,0,0,106,5,0,124,0,0,25, + 106,6,0,83,113,20,0,113,20,0,87,100,1,0,83,100, + 1,0,83,40,2,0,0,0,117,23,0,0,0,70,105,110, + 100,32,97,32,109,111,100,117,108,101,39,115,32,108,111,97, + 100,101,114,46,78,40,7,0,0,0,117,3,0,0,0,115, + 121,115,117,9,0,0,0,109,101,116,97,95,112,97,116,104, + 117,19,0,0,0,95,73,77,80,76,73,67,73,84,95,77, + 69,84,65,95,80,65,84,72,117,11,0,0,0,102,105,110, + 100,95,109,111,100,117,108,101,117,4,0,0,0,78,111,110, + 101,117,7,0,0,0,109,111,100,117,108,101,115,117,10,0, + 0,0,95,95,108,111,97,100,101,114,95,95,40,5,0,0, + 0,117,4,0,0,0,110,97,109,101,117,4,0,0,0,112, + 97,116,104,117,9,0,0,0,109,101,116,97,95,112,97,116, + 104,117,6,0,0,0,102,105,110,100,101,114,117,6,0,0, + 0,108,111,97,100,101,114,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,12,0,0,0,95,102,105,110,100,95,109,111, + 100,117,108,101,151,3,0,0,115,16,0,0,0,0,2,13, + 1,13,1,18,1,12,2,15,1,4,2,21,2,117,12,0, + 0,0,95,102,105,110,100,95,109,111,100,117,108,101,99,3, + 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, + 0,0,0,115,194,0,0,0,116,0,0,124,0,0,116,1, + 0,131,2,0,115,45,0,116,2,0,100,1,0,106,3,0, + 116,4,0,124,0,0,131,1,0,131,1,0,131,1,0,130, + 1,0,110,0,0,124,2,0,100,2,0,107,0,0,114,72, + 0,116,5,0,100,3,0,131,1,0,130,1,0,110,0,0, + 124,1,0,114,156,0,116,0,0,124,1,0,116,1,0,131, + 2,0,115,108,0,116,2,0,100,4,0,131,1,0,130,1, + 0,113,156,0,124,1,0,116,6,0,106,7,0,107,7,0, + 114,156,0,100,5,0,125,3,0,116,8,0,124,3,0,106, + 3,0,124,1,0,131,1,0,131,1,0,130,1,0,113,156, + 0,110,0,0,124,0,0,12,114,190,0,124,2,0,100,2, + 0,107,2,0,114,190,0,116,5,0,100,6,0,131,1,0, + 130,1,0,110,0,0,100,7,0,83,40,8,0,0,0,117, + 28,0,0,0,86,101,114,105,102,121,32,97,114,103,117,109, + 101,110,116,115,32,97,114,101,32,34,115,97,110,101,34,46, + 117,31,0,0,0,109,111,100,117,108,101,32,110,97,109,101, + 32,109,117,115,116,32,98,101,32,115,116,114,44,32,110,111, + 116,32,123,125,105,0,0,0,0,117,18,0,0,0,108,101, + 118,101,108,32,109,117,115,116,32,98,101,32,62,61,32,48, + 117,31,0,0,0,95,95,112,97,99,107,97,103,101,95,95, + 32,110,111,116,32,115,101,116,32,116,111,32,97,32,115,116, + 114,105,110,103,117,62,0,0,0,80,97,114,101,110,116,32, + 109,111,100,117,108,101,32,123,48,33,114,125,32,110,111,116, + 32,108,111,97,100,101,100,44,32,99,97,110,110,111,116,32, + 112,101,114,102,111,114,109,32,114,101,108,97,116,105,118,101, + 32,105,109,112,111,114,116,117,17,0,0,0,69,109,112,116, + 121,32,109,111,100,117,108,101,32,110,97,109,101,78,40,9, + 0,0,0,117,10,0,0,0,105,115,105,110,115,116,97,110, + 99,101,117,3,0,0,0,115,116,114,117,9,0,0,0,84, + 121,112,101,69,114,114,111,114,117,6,0,0,0,102,111,114, + 109,97,116,117,4,0,0,0,116,121,112,101,117,10,0,0, + 0,86,97,108,117,101,69,114,114,111,114,117,3,0,0,0, + 115,121,115,117,7,0,0,0,109,111,100,117,108,101,115,117, + 11,0,0,0,83,121,115,116,101,109,69,114,114,111,114,40, + 4,0,0,0,117,4,0,0,0,110,97,109,101,117,7,0, + 0,0,112,97,99,107,97,103,101,117,5,0,0,0,108,101, + 118,101,108,117,3,0,0,0,109,115,103,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,13,0,0,0,95,115,97,110, + 105,116,121,95,99,104,101,99,107,166,3,0,0,115,24,0, + 0,0,0,2,15,1,30,1,12,1,15,1,6,1,15,1, + 15,1,15,1,6,2,27,1,19,1,117,13,0,0,0,95, + 115,97,110,105,116,121,95,99,104,101,99,107,117,20,0,0, + 0,78,111,32,109,111,100,117,108,101,32,110,97,109,101,100, + 32,123,33,114,125,99,2,0,0,0,0,0,0,0,8,0, + 0,0,20,0,0,0,67,0,0,0,115,205,1,0,0,100, + 9,0,125,2,0,124,0,0,106,1,0,100,1,0,131,1, + 0,100,2,0,25,125,3,0,124,3,0,114,175,0,124,3, + 0,116,2,0,106,3,0,107,7,0,114,59,0,124,1,0, + 124,3,0,131,1,0,1,110,0,0,124,0,0,116,2,0, + 106,3,0,107,6,0,114,85,0,116,2,0,106,3,0,124, + 0,0,25,83,116,2,0,106,3,0,124,3,0,25,125,4, + 0,121,13,0,124,4,0,106,4,0,125,2,0,87,113,175, + 0,4,116,5,0,107,10,0,114,171,0,1,1,1,116,6, + 0,100,3,0,23,106,7,0,124,0,0,124,3,0,131,2, + 0,125,5,0,116,8,0,124,5,0,100,4,0,124,0,0, + 131,1,1,130,1,0,89,113,175,0,88,110,0,0,116,9, + 0,124,0,0,124,2,0,131,2,0,125,6,0,124,6,0, + 100,9,0,107,8,0,114,232,0,116,8,0,116,6,0,106, + 7,0,124,0,0,131,1,0,100,4,0,124,0,0,131,1, + 1,130,1,0,110,47,0,124,0,0,116,2,0,106,3,0, + 107,7,0,114,23,1,124,6,0,106,10,0,124,0,0,131, + 1,0,1,116,11,0,100,5,0,124,0,0,124,6,0,131, + 3,0,1,110,0,0,116,2,0,106,3,0,124,0,0,25, + 125,7,0,124,3,0,114,87,1,116,2,0,106,3,0,124, + 3,0,25,125,4,0,116,12,0,124,4,0,124,0,0,106, + 1,0,100,1,0,131,1,0,100,6,0,25,124,7,0,131, + 3,0,1,110,0,0,116,13,0,124,7,0,100,7,0,131, + 2,0,12,115,118,1,124,7,0,106,14,0,100,9,0,107, + 8,0,114,201,1,121,59,0,124,7,0,106,15,0,124,7, + 0,95,14,0,116,13,0,124,7,0,100,8,0,131,2,0, + 115,176,1,124,7,0,106,14,0,106,1,0,100,1,0,131, + 1,0,100,2,0,25,124,7,0,95,14,0,110,0,0,87, + 113,201,1,4,116,5,0,107,10,0,114,197,1,1,1,1, + 89,113,201,1,88,110,0,0,124,7,0,83,40,10,0,0, + 0,117,25,0,0,0,70,105,110,100,32,97,110,100,32,108, + 111,97,100,32,116,104,101,32,109,111,100,117,108,101,46,117, + 1,0,0,0,46,105,0,0,0,0,117,21,0,0,0,59, + 32,123,125,32,105,115,32,110,111,116,32,97,32,112,97,99, + 107,97,103,101,117,4,0,0,0,110,97,109,101,117,18,0, + 0,0,105,109,112,111,114,116,32,123,33,114,125,32,35,32, + 123,33,114,125,105,2,0,0,0,117,11,0,0,0,95,95, + 112,97,99,107,97,103,101,95,95,117,8,0,0,0,95,95, + 112,97,116,104,95,95,78,40,16,0,0,0,117,4,0,0, + 0,78,111,110,101,117,10,0,0,0,114,112,97,114,116,105, + 116,105,111,110,117,3,0,0,0,115,121,115,117,7,0,0, + 0,109,111,100,117,108,101,115,117,8,0,0,0,95,95,112, + 97,116,104,95,95,117,14,0,0,0,65,116,116,114,105,98, + 117,116,101,69,114,114,111,114,117,8,0,0,0,95,69,82, + 82,95,77,83,71,117,6,0,0,0,102,111,114,109,97,116, + 117,11,0,0,0,73,109,112,111,114,116,69,114,114,111,114, + 117,12,0,0,0,95,102,105,110,100,95,109,111,100,117,108, + 101,117,11,0,0,0,108,111,97,100,95,109,111,100,117,108, + 101,117,15,0,0,0,118,101,114,98,111,115,101,95,109,101, + 115,115,97,103,101,117,7,0,0,0,115,101,116,97,116,116, + 114,117,7,0,0,0,104,97,115,97,116,116,114,117,11,0, + 0,0,95,95,112,97,99,107,97,103,101,95,95,117,8,0, + 0,0,95,95,110,97,109,101,95,95,40,8,0,0,0,117, + 4,0,0,0,110,97,109,101,117,7,0,0,0,105,109,112, + 111,114,116,95,117,4,0,0,0,112,97,116,104,117,6,0, + 0,0,112,97,114,101,110,116,117,13,0,0,0,112,97,114, + 101,110,116,95,109,111,100,117,108,101,117,3,0,0,0,109, + 115,103,117,6,0,0,0,108,111,97,100,101,114,117,6,0, + 0,0,109,111,100,117,108,101,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,14,0,0,0,95,102,105,110,100,95,97, + 110,100,95,108,111,97,100,187,3,0,0,115,62,0,0,0, + 0,2,6,1,19,1,6,1,15,1,13,2,15,1,11,2, + 13,1,3,1,13,1,13,1,22,1,26,1,15,1,12,1, + 30,1,15,2,13,1,19,2,13,1,6,2,13,1,32,2, + 31,1,3,1,12,1,15,1,32,1,13,1,8,1,117,14, + 0,0,0,95,102,105,110,100,95,97,110,100,95,108,111,97, + 100,105,0,0,0,0,99,3,0,0,0,0,0,0,0,5, + 0,0,0,18,0,0,0,67,0,0,0,115,172,0,0,0, + 116,0,0,124,0,0,124,1,0,124,2,0,131,3,0,1, + 124,2,0,100,1,0,107,4,0,114,49,0,116,1,0,124, + 0,0,124,1,0,124,2,0,131,3,0,125,0,0,110,0, + 0,116,2,0,131,0,0,143,108,0,1,121,69,0,116,3, + 0,106,4,0,124,0,0,25,125,3,0,124,3,0,100,4, + 0,107,8,0,114,123,0,100,2,0,106,6,0,124,0,0, + 131,1,0,125,4,0,116,7,0,124,4,0,100,3,0,124, + 0,0,131,1,1,130,1,0,110,0,0,124,3,0,83,87, + 110,18,0,4,116,8,0,107,10,0,114,148,0,1,1,1, + 89,110,1,0,88,116,9,0,124,0,0,116,10,0,131,2, + 0,83,87,100,4,0,81,88,100,4,0,83,40,5,0,0, + 0,117,50,1,0,0,73,109,112,111,114,116,32,97,110,100, + 32,114,101,116,117,114,110,32,116,104,101,32,109,111,100,117, + 108,101,32,98,97,115,101,100,32,111,110,32,105,116,115,32, + 110,97,109,101,44,32,116,104,101,32,112,97,99,107,97,103, + 101,32,116,104,101,32,99,97,108,108,32,105,115,10,32,32, + 32,32,98,101,105,110,103,32,109,97,100,101,32,102,114,111, + 109,44,32,97,110,100,32,116,104,101,32,108,101,118,101,108, + 32,97,100,106,117,115,116,109,101,110,116,46,10,10,32,32, + 32,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32, + 114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,103, + 114,101,97,116,101,115,116,32,99,111,109,109,111,110,32,100, + 101,110,111,109,105,110,97,116,111,114,32,111,102,32,102,117, + 110,99,116,105,111,110,97,108,105,116,121,10,32,32,32,32, + 98,101,116,119,101,101,110,32,105,109,112,111,114,116,95,109, + 111,100,117,108,101,32,97,110,100,32,95,95,105,109,112,111, + 114,116,95,95,46,32,84,104,105,115,32,105,110,99,108,117, + 100,101,115,32,115,101,116,116,105,110,103,32,95,95,112,97, + 99,107,97,103,101,95,95,32,105,102,10,32,32,32,32,116, + 104,101,32,108,111,97,100,101,114,32,100,105,100,32,110,111, + 116,46,10,10,32,32,32,32,105,0,0,0,0,117,40,0, + 0,0,105,109,112,111,114,116,32,111,102,32,123,125,32,104, + 97,108,116,101,100,59,32,78,111,110,101,32,105,110,32,115, + 121,115,46,109,111,100,117,108,101,115,117,4,0,0,0,110, + 97,109,101,78,40,11,0,0,0,117,13,0,0,0,95,115, + 97,110,105,116,121,95,99,104,101,99,107,117,13,0,0,0, + 95,114,101,115,111,108,118,101,95,110,97,109,101,117,18,0, + 0,0,95,73,109,112,111,114,116,76,111,99,107,67,111,110, + 116,101,120,116,117,3,0,0,0,115,121,115,117,7,0,0, + 0,109,111,100,117,108,101,115,117,4,0,0,0,78,111,110, + 101,117,6,0,0,0,102,111,114,109,97,116,117,11,0,0, + 0,73,109,112,111,114,116,69,114,114,111,114,117,8,0,0, + 0,75,101,121,69,114,114,111,114,117,14,0,0,0,95,102, + 105,110,100,95,97,110,100,95,108,111,97,100,117,11,0,0, + 0,95,103,99,100,95,105,109,112,111,114,116,40,5,0,0, + 0,117,4,0,0,0,110,97,109,101,117,7,0,0,0,112, + 97,99,107,97,103,101,117,5,0,0,0,108,101,118,101,108, + 117,6,0,0,0,109,111,100,117,108,101,117,7,0,0,0, + 109,101,115,115,97,103,101,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,11,0,0,0,95,103,99,100,95,105,109,112, + 111,114,116,228,3,0,0,115,28,0,0,0,0,9,16,1, + 12,1,21,1,10,1,3,1,13,1,12,1,6,1,9,1, + 21,1,8,1,13,1,5,1,117,11,0,0,0,95,103,99, + 100,95,105,109,112,111,114,116,99,3,0,0,0,0,0,0, + 0,4,0,0,0,13,0,0,0,3,0,0,0,115,179,0, + 0,0,116,0,0,136,0,0,100,1,0,131,2,0,114,175, + 0,100,2,0,124,1,0,107,6,0,114,86,0,116,0,0, + 136,0,0,100,3,0,131,2,0,114,86,0,116,1,0,124, + 1,0,131,1,0,125,1,0,124,1,0,106,2,0,100,2, + 0,131,1,0,1,124,1,0,106,3,0,136,0,0,106,4, + 0,131,1,0,1,110,0,0,120,86,0,135,0,0,102,1, + 0,100,4,0,100,5,0,134,0,0,124,1,0,68,131,1, + 0,68,93,56,0,125,3,0,121,29,0,124,2,0,100,6, + 0,106,5,0,136,0,0,106,6,0,124,3,0,131,2,0, + 131,1,0,1,87,113,112,0,4,116,7,0,107,10,0,114, + 167,0,1,1,1,89,113,112,0,88,113,112,0,87,110,0, + 0,136,0,0,83,40,7,0,0,0,117,238,0,0,0,70, + 105,103,117,114,101,32,111,117,116,32,119,104,97,116,32,95, + 95,105,109,112,111,114,116,95,95,32,115,104,111,117,108,100, + 32,114,101,116,117,114,110,46,10,10,32,32,32,32,84,104, + 101,32,105,109,112,111,114,116,95,32,112,97,114,97,109,101, + 116,101,114,32,105,115,32,97,32,99,97,108,108,97,98,108, + 101,32,119,104,105,99,104,32,116,97,107,101,115,32,116,104, + 101,32,110,97,109,101,32,111,102,32,109,111,100,117,108,101, + 32,116,111,10,32,32,32,32,105,109,112,111,114,116,46,32, + 73,116,32,105,115,32,114,101,113,117,105,114,101,100,32,116, + 111,32,100,101,99,111,117,112,108,101,32,116,104,101,32,102, + 117,110,99,116,105,111,110,32,102,114,111,109,32,97,115,115, + 117,109,105,110,103,32,105,109,112,111,114,116,108,105,98,39, + 115,10,32,32,32,32,105,109,112,111,114,116,32,105,109,112, + 108,101,109,101,110,116,97,116,105,111,110,32,105,115,32,100, + 101,115,105,114,101,100,46,10,10,32,32,32,32,117,8,0, + 0,0,95,95,112,97,116,104,95,95,117,1,0,0,0,42, + 117,7,0,0,0,95,95,97,108,108,95,95,99,1,0,0, + 0,0,0,0,0,2,0,0,0,4,0,0,0,51,0,0, + 0,115,36,0,0,0,124,0,0,93,26,0,125,1,0,116, + 0,0,136,0,0,124,1,0,131,2,0,115,3,0,124,1, + 0,86,1,113,3,0,100,0,0,83,40,1,0,0,0,78, + 40,1,0,0,0,117,7,0,0,0,104,97,115,97,116,116, + 114,40,2,0,0,0,117,2,0,0,0,46,48,117,1,0, + 0,0,121,40,1,0,0,0,117,6,0,0,0,109,111,100, + 117,108,101,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,9,0,0,0,60, + 103,101,110,101,120,112,114,62,12,4,0,0,115,2,0,0, + 0,6,0,117,35,0,0,0,95,104,97,110,100,108,101,95, + 102,114,111,109,108,105,115,116,46,60,108,111,99,97,108,115, + 62,46,60,103,101,110,101,120,112,114,62,117,7,0,0,0, + 123,48,125,46,123,49,125,40,8,0,0,0,117,7,0,0, + 0,104,97,115,97,116,116,114,117,4,0,0,0,108,105,115, + 116,117,6,0,0,0,114,101,109,111,118,101,117,6,0,0, + 0,101,120,116,101,110,100,117,7,0,0,0,95,95,97,108, + 108,95,95,117,6,0,0,0,102,111,114,109,97,116,117,8, + 0,0,0,95,95,110,97,109,101,95,95,117,11,0,0,0, + 73,109,112,111,114,116,69,114,114,111,114,40,4,0,0,0, + 117,6,0,0,0,109,111,100,117,108,101,117,8,0,0,0, + 102,114,111,109,108,105,115,116,117,7,0,0,0,105,109,112, + 111,114,116,95,117,1,0,0,0,120,40,0,0,0,0,40, + 1,0,0,0,117,6,0,0,0,109,111,100,117,108,101,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,16,0,0,0,95,104,97,110,100,108,101,95,102,114, + 111,109,108,105,115,116,253,3,0,0,115,22,0,0,0,0, + 10,15,1,27,1,12,1,13,1,19,1,32,1,3,1,29, + 1,13,1,12,1,117,16,0,0,0,95,104,97,110,100,108, + 101,95,102,114,111,109,108,105,115,116,99,1,0,0,0,0, + 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, + 78,0,0,0,124,0,0,106,0,0,100,1,0,131,1,0, + 125,1,0,124,1,0,100,6,0,107,8,0,114,74,0,124, + 0,0,100,2,0,25,125,1,0,100,3,0,124,0,0,107, + 7,0,114,74,0,124,1,0,106,2,0,100,4,0,131,1, + 0,100,5,0,25,125,1,0,113,74,0,110,0,0,124,1, + 0,83,40,7,0,0,0,117,167,0,0,0,67,97,108,99, + 117,108,97,116,101,32,119,104,97,116,32,95,95,112,97,99, + 107,97,103,101,95,95,32,115,104,111,117,108,100,32,98,101, + 46,10,10,32,32,32,32,95,95,112,97,99,107,97,103,101, + 95,95,32,105,115,32,110,111,116,32,103,117,97,114,97,110, + 116,101,101,100,32,116,111,32,98,101,32,100,101,102,105,110, + 101,100,32,111,114,32,99,111,117,108,100,32,98,101,32,115, + 101,116,32,116,111,32,78,111,110,101,10,32,32,32,32,116, + 111,32,114,101,112,114,101,115,101,110,116,32,116,104,97,116, + 32,105,116,115,32,112,114,111,112,101,114,32,118,97,108,117, + 101,32,105,115,32,117,110,107,110,111,119,110,46,10,10,32, + 32,32,32,117,11,0,0,0,95,95,112,97,99,107,97,103, + 101,95,95,117,8,0,0,0,95,95,110,97,109,101,95,95, + 117,8,0,0,0,95,95,112,97,116,104,95,95,117,1,0, + 0,0,46,105,0,0,0,0,78,40,3,0,0,0,117,3, + 0,0,0,103,101,116,117,4,0,0,0,78,111,110,101,117, + 10,0,0,0,114,112,97,114,116,105,116,105,111,110,40,2, + 0,0,0,117,7,0,0,0,103,108,111,98,97,108,115,117, + 7,0,0,0,112,97,99,107,97,103,101,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,17,0,0,0,95,99,97,108, + 99,95,95,95,112,97,99,107,97,103,101,95,95,20,4,0, + 0,115,12,0,0,0,0,7,15,1,12,1,10,1,12,1, + 25,1,117,17,0,0,0,95,99,97,108,99,95,95,95,112, + 97,99,107,97,103,101,95,95,99,5,0,0,0,0,0,0, + 0,8,0,0,0,4,0,0,0,67,0,0,0,115,192,0, + 0,0,124,4,0,100,1,0,107,2,0,114,27,0,116,0, + 0,124,0,0,131,1,0,125,5,0,110,30,0,116,1,0, + 124,1,0,131,1,0,125,6,0,116,0,0,124,0,0,124, + 6,0,124,4,0,131,3,0,125,5,0,124,3,0,115,172, + 0,124,4,0,100,1,0,107,2,0,114,99,0,116,2,0, + 106,3,0,124,0,0,106,4,0,100,2,0,131,1,0,100, + 1,0,25,25,83,124,0,0,115,109,0,124,5,0,83,116, + 5,0,124,0,0,131,1,0,116,5,0,124,0,0,106,4, + 0,100,2,0,131,1,0,100,1,0,25,131,1,0,24,125, + 7,0,116,2,0,106,3,0,124,5,0,106,6,0,100,3, + 0,124,7,0,11,133,2,0,25,25,83,110,16,0,116,7, + 0,124,5,0,124,3,0,116,0,0,131,3,0,83,100,3, + 0,83,40,4,0,0,0,117,214,1,0,0,73,109,112,111, + 114,116,32,97,32,109,111,100,117,108,101,46,10,10,32,32, + 32,32,84,104,101,32,39,103,108,111,98,97,108,115,39,32, + 97,114,103,117,109,101,110,116,32,105,115,32,117,115,101,100, + 32,116,111,32,105,110,102,101,114,32,119,104,101,114,101,32, + 116,104,101,32,105,109,112,111,114,116,32,105,115,32,111,99, + 99,117,114,105,110,103,32,102,114,111,109,10,32,32,32,32, + 116,111,32,104,97,110,100,108,101,32,114,101,108,97,116,105, + 118,101,32,105,109,112,111,114,116,115,46,32,84,104,101,32, + 39,108,111,99,97,108,115,39,32,97,114,103,117,109,101,110, + 116,32,105,115,32,105,103,110,111,114,101,100,46,32,84,104, + 101,10,32,32,32,32,39,102,114,111,109,108,105,115,116,39, + 32,97,114,103,117,109,101,110,116,32,115,112,101,99,105,102, + 105,101,115,32,119,104,97,116,32,115,104,111,117,108,100,32, + 101,120,105,115,116,32,97,115,32,97,116,116,114,105,98,117, + 116,101,115,32,111,110,32,116,104,101,32,109,111,100,117,108, + 101,10,32,32,32,32,98,101,105,110,103,32,105,109,112,111, + 114,116,101,100,32,40,101,46,103,46,32,96,96,102,114,111, + 109,32,109,111,100,117,108,101,32,105,109,112,111,114,116,32, + 60,102,114,111,109,108,105,115,116,62,96,96,41,46,32,32, + 84,104,101,32,39,108,101,118,101,108,39,10,32,32,32,32, + 97,114,103,117,109,101,110,116,32,114,101,112,114,101,115,101, + 110,116,115,32,116,104,101,32,112,97,99,107,97,103,101,32, + 108,111,99,97,116,105,111,110,32,116,111,32,105,109,112,111, + 114,116,32,102,114,111,109,32,105,110,32,97,32,114,101,108, + 97,116,105,118,101,10,32,32,32,32,105,109,112,111,114,116, + 32,40,101,46,103,46,32,96,96,102,114,111,109,32,46,46, + 112,107,103,32,105,109,112,111,114,116,32,109,111,100,96,96, + 32,119,111,117,108,100,32,104,97,118,101,32,97,32,39,108, + 101,118,101,108,39,32,111,102,32,50,41,46,10,10,32,32, + 32,32,105,0,0,0,0,117,1,0,0,0,46,78,40,8, + 0,0,0,117,11,0,0,0,95,103,99,100,95,105,109,112, + 111,114,116,117,17,0,0,0,95,99,97,108,99,95,95,95, + 112,97,99,107,97,103,101,95,95,117,3,0,0,0,115,121, + 115,117,7,0,0,0,109,111,100,117,108,101,115,117,9,0, + 0,0,112,97,114,116,105,116,105,111,110,117,3,0,0,0, + 108,101,110,117,8,0,0,0,95,95,110,97,109,101,95,95, + 117,16,0,0,0,95,104,97,110,100,108,101,95,102,114,111, + 109,108,105,115,116,40,8,0,0,0,117,4,0,0,0,110, + 97,109,101,117,7,0,0,0,103,108,111,98,97,108,115,117, + 6,0,0,0,108,111,99,97,108,115,117,8,0,0,0,102, + 114,111,109,108,105,115,116,117,5,0,0,0,108,101,118,101, + 108,117,6,0,0,0,109,111,100,117,108,101,117,7,0,0, + 0,112,97,99,107,97,103,101,117,7,0,0,0,99,117,116, + 95,111,102,102,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,35, + 4,0,0,115,24,0,0,0,0,11,12,1,15,2,12,1, + 18,1,6,3,12,1,24,1,6,1,4,2,35,1,28,2, + 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,99, + 2,0,0,0,0,0,0,0,9,0,0,0,12,0,0,0, + 67,0,0,0,115,109,1,0,0,124,1,0,97,0,0,124, + 0,0,97,1,0,120,47,0,116,0,0,116,1,0,102,2, + 0,68,93,33,0,125,2,0,116,2,0,124,2,0,100,1, + 0,131,2,0,115,25,0,116,3,0,124,2,0,95,4,0, + 113,25,0,113,25,0,87,116,1,0,106,5,0,116,6,0, + 25,125,3,0,120,76,0,100,17,0,68,93,68,0,125,4, + 0,124,4,0,116,1,0,106,5,0,107,7,0,114,121,0, + 116,3,0,106,7,0,124,4,0,131,1,0,125,5,0,110, + 13,0,116,1,0,106,5,0,124,4,0,25,125,5,0,116, + 8,0,124,3,0,124,4,0,124,5,0,131,3,0,1,113, + 82,0,87,120,153,0,100,18,0,100,19,0,100,20,0,103, + 3,0,68,93,124,0,92,2,0,125,6,0,125,7,0,124, + 6,0,116,1,0,106,5,0,107,6,0,114,214,0,116,1, + 0,106,5,0,124,6,0,25,125,8,0,80,113,170,0,121, + 56,0,116,3,0,106,7,0,124,6,0,131,1,0,125,8, + 0,124,6,0,100,10,0,107,2,0,114,12,1,100,11,0, + 116,1,0,106,9,0,107,6,0,114,12,1,100,7,0,125, + 7,0,110,0,0,80,87,113,170,0,4,116,10,0,107,10, + 0,114,37,1,1,1,1,119,170,0,89,113,170,0,88,113, + 170,0,87,116,10,0,100,12,0,131,1,0,130,1,0,116, + 8,0,124,3,0,100,13,0,124,8,0,131,3,0,1,116, + 8,0,124,3,0,100,14,0,124,7,0,131,3,0,1,116, + 8,0,124,3,0,100,15,0,116,11,0,131,0,0,131,3, + 0,1,100,16,0,83,40,21,0,0,0,117,249,0,0,0, + 83,101,116,117,112,32,105,109,112,111,114,116,108,105,98,32, + 98,121,32,105,109,112,111,114,116,105,110,103,32,110,101,101, + 100,101,100,32,98,117,105,108,116,45,105,110,32,109,111,100, + 117,108,101,115,32,97,110,100,32,105,110,106,101,99,116,105, + 110,103,32,116,104,101,109,10,32,32,32,32,105,110,116,111, + 32,116,104,101,32,103,108,111,98,97,108,32,110,97,109,101, + 115,112,97,99,101,46,10,10,32,32,32,32,65,115,32,115, + 121,115,32,105,115,32,110,101,101,100,101,100,32,102,111,114, + 32,115,121,115,46,109,111,100,117,108,101,115,32,97,99,99, + 101,115,115,32,97,110,100,32,105,109,112,32,105,115,32,110, + 101,101,100,101,100,32,116,111,32,108,111,97,100,32,98,117, + 105,108,116,45,105,110,10,32,32,32,32,109,111,100,117,108, + 101,115,44,32,116,104,111,115,101,32,116,119,111,32,109,111, + 100,117,108,101,115,32,109,117,115,116,32,98,101,32,101,120, + 112,108,105,99,105,116,108,121,32,112,97,115,115,101,100,32, + 105,110,46,10,10,32,32,32,32,117,10,0,0,0,95,95, + 108,111,97,100,101,114,95,95,117,3,0,0,0,95,105,111, + 117,9,0,0,0,95,119,97,114,110,105,110,103,115,117,8, + 0,0,0,98,117,105,108,116,105,110,115,117,7,0,0,0, + 109,97,114,115,104,97,108,117,5,0,0,0,112,111,115,105, + 120,117,1,0,0,0,47,117,2,0,0,0,110,116,117,1, + 0,0,0,92,117,3,0,0,0,111,115,50,117,7,0,0, + 0,69,77,88,32,71,67,67,117,30,0,0,0,105,109,112, + 111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,32, + 112,111,115,105,120,32,111,114,32,110,116,117,3,0,0,0, + 95,111,115,117,8,0,0,0,112,97,116,104,95,115,101,112, + 117,11,0,0,0,95,114,101,108,97,120,95,99,97,115,101, + 78,40,4,0,0,0,117,3,0,0,0,95,105,111,117,9, + 0,0,0,95,119,97,114,110,105,110,103,115,117,8,0,0, + 0,98,117,105,108,116,105,110,115,117,7,0,0,0,109,97, + 114,115,104,97,108,40,2,0,0,0,117,5,0,0,0,112, + 111,115,105,120,117,1,0,0,0,47,40,2,0,0,0,117, + 2,0,0,0,110,116,117,1,0,0,0,92,40,2,0,0, + 0,117,3,0,0,0,111,115,50,117,1,0,0,0,92,40, + 12,0,0,0,117,3,0,0,0,105,109,112,117,3,0,0, + 0,115,121,115,117,7,0,0,0,104,97,115,97,116,116,114, + 117,15,0,0,0,66,117,105,108,116,105,110,73,109,112,111, + 114,116,101,114,117,10,0,0,0,95,95,108,111,97,100,101, + 114,95,95,117,7,0,0,0,109,111,100,117,108,101,115,117, + 8,0,0,0,95,95,110,97,109,101,95,95,117,11,0,0, + 0,108,111,97,100,95,109,111,100,117,108,101,117,7,0,0, + 0,115,101,116,97,116,116,114,117,7,0,0,0,118,101,114, + 115,105,111,110,117,11,0,0,0,73,109,112,111,114,116,69, + 114,114,111,114,117,16,0,0,0,95,109,97,107,101,95,114, + 101,108,97,120,95,99,97,115,101,40,9,0,0,0,117,10, + 0,0,0,115,121,115,95,109,111,100,117,108,101,117,10,0, + 0,0,105,109,112,95,109,111,100,117,108,101,117,6,0,0, + 0,109,111,100,117,108,101,117,11,0,0,0,115,101,108,102, + 95,109,111,100,117,108,101,117,12,0,0,0,98,117,105,108, + 116,105,110,95,110,97,109,101,117,14,0,0,0,98,117,105, + 108,116,105,110,95,109,111,100,117,108,101,117,10,0,0,0, + 98,117,105,108,116,105,110,95,111,115,117,8,0,0,0,112, + 97,116,104,95,115,101,112,117,9,0,0,0,111,115,95,109, + 111,100,117,108,101,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,6,0,0,0,95,115,101,116,117,112,65,4,0,0, + 115,52,0,0,0,0,9,6,1,6,2,19,1,15,1,16, + 2,13,1,13,1,15,1,18,2,13,1,20,2,28,1,15, + 1,13,1,4,2,3,1,15,2,27,1,9,1,5,1,13, + 1,12,2,12,1,16,1,16,2,117,6,0,0,0,95,115, + 101,116,117,112,99,2,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,67,0,0,0,115,44,0,0,0,116,0, + 0,124,0,0,124,1,0,131,2,0,1,116,1,0,106,2, + 0,125,2,0,116,2,0,116,1,0,95,2,0,124,2,0, + 116,1,0,95,3,0,100,1,0,83,40,2,0,0,0,117, + 201,0,0,0,73,110,115,116,97,108,108,32,105,109,112,111, + 114,116,108,105,98,32,97,115,32,116,104,101,32,105,109,112, + 108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,105, + 109,112,111,114,116,46,10,10,32,32,32,32,73,116,32,105, + 115,32,97,115,115,117,109,101,100,32,116,104,97,116,32,105, + 109,112,32,97,110,100,32,115,121,115,32,104,97,118,101,32, + 98,101,101,110,32,105,109,112,111,114,116,101,100,32,97,110, + 100,32,105,110,106,101,99,116,101,100,32,105,110,116,111,32, + 116,104,101,10,32,32,32,32,103,108,111,98,97,108,32,110, + 97,109,101,115,112,97,99,101,32,102,111,114,32,116,104,101, + 32,109,111,100,117,108,101,32,112,114,105,111,114,32,116,111, + 32,99,97,108,108,105,110,103,32,116,104,105,115,32,102,117, + 110,99,116,105,111,110,46,10,10,32,32,32,32,78,40,4, + 0,0,0,117,6,0,0,0,95,115,101,116,117,112,117,8, + 0,0,0,98,117,105,108,116,105,110,115,117,10,0,0,0, + 95,95,105,109,112,111,114,116,95,95,117,19,0,0,0,95, + 95,111,114,105,103,105,110,97,108,95,105,109,112,111,114,116, + 95,95,40,3,0,0,0,117,10,0,0,0,115,121,115,95, + 109,111,100,117,108,101,117,10,0,0,0,105,109,112,95,109, + 111,100,117,108,101,117,11,0,0,0,111,114,105,103,95,105, + 109,112,111,114,116,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,8,0,0,0,95,105,110,115,116,97,108,108,110,4, + 0,0,115,8,0,0,0,0,7,13,1,9,1,9,1,117, + 8,0,0,0,95,105,110,115,116,97,108,108,78,40,3,0, + 0,0,117,3,0,0,0,119,105,110,117,6,0,0,0,99, + 121,103,119,105,110,117,6,0,0,0,100,97,114,119,105,110, + 40,55,0,0,0,117,7,0,0,0,95,95,100,111,99,95, + 95,117,26,0,0,0,67,65,83,69,95,73,78,83,69,78, + 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, + 117,16,0,0,0,95,109,97,107,101,95,114,101,108,97,120, + 95,99,97,115,101,117,7,0,0,0,95,119,95,108,111,110, + 103,117,7,0,0,0,95,114,95,108,111,110,103,117,10,0, + 0,0,95,112,97,116,104,95,106,111,105,110,117,12,0,0, + 0,95,112,97,116,104,95,101,120,105,115,116,115,117,18,0, + 0,0,95,112,97,116,104,95,105,115,95,109,111,100,101,95, + 116,121,112,101,117,12,0,0,0,95,112,97,116,104,95,105, + 115,102,105,108,101,117,11,0,0,0,95,112,97,116,104,95, + 105,115,100,105,114,117,17,0,0,0,95,112,97,116,104,95, + 119,105,116,104,111,117,116,95,101,120,116,117,14,0,0,0, + 95,112,97,116,104,95,97,98,115,111,108,117,116,101,117,13, + 0,0,0,95,119,114,105,116,101,95,97,116,111,109,105,99, + 117,5,0,0,0,95,119,114,97,112,117,4,0,0,0,116, + 121,112,101,117,8,0,0,0,95,95,99,111,100,101,95,95, + 117,9,0,0,0,99,111,100,101,95,116,121,112,101,117,15, + 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, + 103,101,117,11,0,0,0,115,101,116,95,112,97,99,107,97, + 103,101,117,10,0,0,0,115,101,116,95,108,111,97,100,101, + 114,117,17,0,0,0,109,111,100,117,108,101,95,102,111,114, + 95,108,111,97,100,101,114,117,11,0,0,0,95,99,104,101, + 99,107,95,110,97,109,101,117,17,0,0,0,95,114,101,113, + 117,105,114,101,115,95,98,117,105,108,116,105,110,117,16,0, + 0,0,95,114,101,113,117,105,114,101,115,95,102,114,111,122, + 101,110,117,12,0,0,0,95,115,117,102,102,105,120,95,108, + 105,115,116,117,15,0,0,0,66,117,105,108,116,105,110,73, + 109,112,111,114,116,101,114,117,14,0,0,0,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,117,13,0,0,0,95, + 76,111,97,100,101,114,66,97,115,105,99,115,117,12,0,0, + 0,83,111,117,114,99,101,76,111,97,100,101,114,117,11,0, + 0,0,95,70,105,108,101,76,111,97,100,101,114,117,17,0, + 0,0,95,83,111,117,114,99,101,70,105,108,101,76,111,97, + 100,101,114,117,21,0,0,0,95,83,111,117,114,99,101,108, + 101,115,115,70,105,108,101,76,111,97,100,101,114,117,20,0, + 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,117,10,0,0,0,80,97,116,104,70, + 105,110,100,101,114,117,11,0,0,0,95,70,105,108,101,70, + 105,110,100,101,114,117,20,0,0,0,95,83,111,117,114,99, + 101,70,105,110,100,101,114,68,101,116,97,105,108,115,117,24, + 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, + 110,100,101,114,68,101,116,97,105,108,115,117,23,0,0,0, + 95,69,120,116,101,110,115,105,111,110,70,105,110,100,101,114, + 68,101,116,97,105,108,115,117,15,0,0,0,95,102,105,108, + 101,95,112,97,116,104,95,104,111,111,107,117,18,0,0,0, + 95,68,69,70,65,85,76,84,95,80,65,84,72,95,72,79, + 79,75,117,18,0,0,0,95,68,101,102,97,117,108,116,80, + 97,116,104,70,105,110,100,101,114,117,18,0,0,0,95,73, + 109,112,111,114,116,76,111,99,107,67,111,110,116,101,120,116, + 117,13,0,0,0,95,114,101,115,111,108,118,101,95,110,97, + 109,101,117,12,0,0,0,95,102,105,110,100,95,109,111,100, + 117,108,101,117,13,0,0,0,95,115,97,110,105,116,121,95, + 99,104,101,99,107,117,19,0,0,0,95,73,77,80,76,73, + 67,73,84,95,77,69,84,65,95,80,65,84,72,117,8,0, + 0,0,95,69,82,82,95,77,83,71,117,14,0,0,0,95, + 102,105,110,100,95,97,110,100,95,108,111,97,100,117,4,0, + 0,0,78,111,110,101,117,11,0,0,0,95,103,99,100,95, + 105,109,112,111,114,116,117,16,0,0,0,95,104,97,110,100, + 108,101,95,102,114,111,109,108,105,115,116,117,17,0,0,0, + 95,99,97,108,99,95,95,95,112,97,99,107,97,103,101,95, + 95,117,10,0,0,0,95,95,105,109,112,111,114,116,95,95, + 117,6,0,0,0,95,115,101,116,117,112,117,8,0,0,0, + 95,105,110,115,116,97,108,108,40,0,0,0,0,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,8,0,0,0,60,109, + 111,100,117,108,101,62,8,0,0,0,115,102,0,0,0,6, + 14,6,3,12,13,12,16,12,15,12,6,12,10,12,10,12, + 6,12,7,12,9,12,13,12,21,12,8,15,4,12,8,12, + 13,12,11,12,32,12,16,12,11,12,11,12,8,19,53,19, + 47,19,77,22,114,19,22,25,38,25,24,19,45,19,68,19, + 75,19,8,19,9,19,11,12,10,6,2,22,21,19,13,12, + 9,12,15,12,17,15,2,6,2,12,41,18,25,12,23,12, + 15,24,30,12,45, +}; diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -79,6 +79,7 @@ interp->codec_error_registry = NULL; interp->codecs_initialized = 0; interp->fscodec_initialized = 0; + interp->importlib = NULL; #ifdef HAVE_DLOPEN #ifdef RTLD_NOW interp->dlopenflags = RTLD_NOW; @@ -116,6 +117,7 @@ Py_CLEAR(interp->modules_reloading); Py_CLEAR(interp->sysdict); Py_CLEAR(interp->builtins); + Py_CLEAR(interp->importlib); } diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -190,6 +190,58 @@ #endif } +static void +import_init(PyInterpreterState *interp, PyObject *sysmod) +{ + PyObject *importlib; + PyObject *impmod; + PyObject *sys_modules; + PyObject *value; + + /* Import _importlib through its frozen version, _frozen_importlib. */ + /* XXX(bcannon): The file path for _frozen_importlib is completely off + */ + if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) { + Py_FatalError("Py_Initialize: can't import _frozen_importlib"); + } + else if (Py_VerboseFlag) { + PySys_FormatStderr("import _frozen_importlib # frozen\n"); + } + importlib = PyImport_AddModule("_frozen_importlib"); + if (importlib == NULL) { + Py_FatalError("Py_Initialize: couldn't get _frozen_importlib from " + "sys.modules"); + } + interp->importlib = importlib; + Py_INCREF(interp->importlib); + + /* Install _importlib as __import__ */ + impmod = PyInit_imp(); + if (impmod == NULL) { + Py_FatalError("Py_Initialize: can't import imp"); + } + else if (Py_VerboseFlag) { + PySys_FormatStderr("import imp # builtin\n"); + } + sys_modules = PyImport_GetModuleDict(); + if (Py_VerboseFlag) { + PySys_FormatStderr("import sys # builtin\n"); + } + if (PyDict_SetItemString(sys_modules, "imp", impmod) < 0) { + Py_FatalError("Py_Initialize: can't save imp to sys.modules"); + } + + value = PyObject_CallMethod(importlib, "_setup", "OO", sysmod, impmod); + if (value == NULL) { + PyErr_Print(); + Py_FatalError("Py_Initialize: importlib install failed"); + } + Py_DECREF(value); + + _PyImportZip_Init(); +} + + void Py_InitializeEx(int install_sigs) { @@ -281,7 +333,7 @@ Py_INCREF(interp->builtins); /* initialize builtin exceptions */ - _PyExc_Init(); + _PyExc_Init(bimod); sysmod = _PySys_Init(); if (sysmod == NULL) @@ -315,6 +367,8 @@ /* Initialize _warnings. */ _PyWarnings_Init(); + import_init(interp, sysmod); + _PyTime_Init(); if (initfsencoding(interp) < 0) @@ -638,11 +692,12 @@ } /* initialize builtin exceptions */ - _PyExc_Init(); + _PyExc_Init(bimod); sysmod = _PyImport_FindBuiltin("sys"); if (bimod != NULL && sysmod != NULL) { PyObject *pstderr; + interp->sysdict = PyModule_GetDict(sysmod); if (interp->sysdict == NULL) goto handle_error; @@ -661,6 +716,8 @@ _PyImportHooks_Init(); + import_init(interp, sysmod); + if (initfsencoding(interp) < 0) goto handle_error; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 20:23:55 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2012 20:23:55 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Undo_a_C99_idiom=2E?= Message-ID: http://hg.python.org/cpython/rev/6cfb6fb18e1f changeset: 76304:6cfb6fb18e1f user: Brett Cannon date: Sat Apr 14 14:23:49 2012 -0400 summary: Undo a C99 idiom. files: Python/import.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2889,12 +2889,12 @@ Py_INCREF(package); if (_PyDict_GetItemId(globals, &PyId___path__) == NULL) { + PyObject *partition = NULL; PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot); if (borrowed_dot == NULL) { goto error; } - PyObject *partition = PyUnicode_RPartition(package, - borrowed_dot); + partition = PyUnicode_RPartition(package, borrowed_dot); Py_DECREF(package); if (partition == NULL) { goto error; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 20:38:23 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2012 20:38:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Try_to_fix_a_sporadic_test_?= =?utf8?q?failure_from_what_is_probably_a_caching_race?= Message-ID: http://hg.python.org/cpython/rev/b85818a836e3 changeset: 76305:b85818a836e3 user: Brett Cannon date: Sat Apr 14 14:38:19 2012 -0400 summary: Try to fix a sporadic test failure from what is probably a caching race condition. files: Lib/test/test_import.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -172,6 +172,7 @@ # Need to be able to load from current dir. sys.path.append('') + importlib.invalidate_caches() try: make_legacy_pyc(filename) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 21:06:21 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 14 Apr 2012 21:06:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_an_import_race_conditio?= =?utf8?q?n=2E?= Message-ID: http://hg.python.org/cpython/rev/02f251c41a17 changeset: 76306:02f251c41a17 user: Brett Cannon date: Sat Apr 14 15:06:17 2012 -0400 summary: Fix an import race condition. files: Lib/test/test_coding.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_coding.py b/Lib/test/test_coding.py --- a/Lib/test/test_coding.py +++ b/Lib/test/test_coding.py @@ -1,7 +1,6 @@ - import test.support, unittest from test.support import TESTFN, unlink, unload -import os, sys +import importlib, os, sys class CodingTest(unittest.TestCase): def test_bad_coding(self): @@ -40,6 +39,7 @@ f.write("'A very long string %s'\n" % ("X" * 1000)) f.close() + importlib.invalidate_caches() __import__(TESTFN) finally: f.close() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 21:20:43 2012 From: python-checkins at python.org (brian.curtin) Date: Sat, 14 Apr 2012 21:20:43 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_Windows_build?= Message-ID: http://hg.python.org/cpython/rev/c5da5a2a9262 changeset: 76307:c5da5a2a9262 parent: 76305:b85818a836e3 user: Brian Curtin date: Sat Apr 14 14:19:33 2012 -0500 summary: Fix Windows build files: Python/import.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2963,7 +2963,7 @@ Py_INCREF(abs_name); } -#if WITH_THREAD +#ifdef WITH_THREAD _PyImport_AcquireLock(); #endif /* From this point forward, goto error_with_unlock! */ @@ -2999,13 +2999,14 @@ if (PyObject_Not(fromlist)) { if (level == 0 || PyUnicode_GET_LENGTH(name) > 0) { PyObject *front = NULL; + PyObject *partition = NULL; PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot); if (borrowed_dot == NULL) { goto error_with_unlock; } - PyObject *partition = PyUnicode_Partition(name, borrowed_dot); + partition = PyUnicode_Partition(name, borrowed_dot); if (partition == NULL) { goto error_with_unlock; } @@ -3043,7 +3044,7 @@ NULL); } error_with_unlock: -#if WITH_THREAD +#ifdef WITH_THREAD if (_PyImport_ReleaseLock() < 0) { PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 14 21:20:43 2012 From: python-checkins at python.org (brian.curtin) Date: Sat, 14 Apr 2012 21:20:43 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_with_the_tip?= Message-ID: http://hg.python.org/cpython/rev/13307eb5bf47 changeset: 76308:13307eb5bf47 parent: 76307:c5da5a2a9262 parent: 76306:02f251c41a17 user: Brian Curtin date: Sat Apr 14 14:20:29 2012 -0500 summary: merge with the tip files: Lib/test/test_coding.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_coding.py b/Lib/test/test_coding.py --- a/Lib/test/test_coding.py +++ b/Lib/test/test_coding.py @@ -1,7 +1,6 @@ - import test.support, unittest from test.support import TESTFN, unlink, unload -import os, sys +import importlib, os, sys class CodingTest(unittest.TestCase): def test_bad_coding(self): @@ -40,6 +39,7 @@ f.write("'A very long string %s'\n" % ("X" * 1000)) f.close() + importlib.invalidate_caches() __import__(TESTFN) finally: f.close() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 02:44:30 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 02:44:30 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Add_some_comments=2E?= Message-ID: http://hg.python.org/cpython/rev/e2f48b076012 changeset: 76309:e2f48b076012 user: Brett Cannon date: Sat Apr 14 18:37:07 2012 -0400 summary: Add some comments. files: Lib/importlib/_bootstrap.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -805,6 +805,7 @@ else: cache = self._path_cache cache_module = tail_module + # Check if the module is the name of a directory (and thus a package). if cache_module in cache: base_path = _path_join(self.path, tail_module) if _path_isdir(base_path): @@ -816,6 +817,7 @@ else: msg = "Not importing directory {}: missing __init__" _warnings.warn(msg.format(base_path), ImportWarning) + # Check for a file w/ a proper suffix exists. for suffix, loader in self.modules: if cache_module + suffix in cache: full_path = _path_join(self.path, tail_module + suffix) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 02:44:31 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 02:44:31 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_IDLE_was_relying_on_implici?= =?utf8?q?t_relative_imports_which_have_gone_away_in?= Message-ID: http://hg.python.org/cpython/rev/556b9bafdee8 changeset: 76310:556b9bafdee8 user: Brett Cannon date: Sat Apr 14 20:44:23 2012 -0400 summary: IDLE was relying on implicit relative imports which have gone away in Python 3.3 thanks to importlib finishing the work in PEP 328 that accidently got carried forward. files: Lib/idlelib/EditorWindow.py | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -1,8 +1,9 @@ -import sys +import imp +import importlib import os import re import string -import imp +import sys from tkinter import * import tkinter.simpledialog as tkSimpleDialog import tkinter.messagebox as tkMessageBox @@ -1005,7 +1006,10 @@ def load_extension(self, name): try: - mod = __import__(name, globals(), locals(), []) + try: + mod = importlib.import_module('.' + name, package=__package__) + except ImportError: + mod = importlib.import_module(name) except ImportError: print("\nFailed to import extension: ", name) raise -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 03:50:06 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 03:50:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Rebuild_importlib=2Eh_to_in?= =?utf8?q?corporate_added_comments=2E?= Message-ID: http://hg.python.org/cpython/rev/6a77697d2a63 changeset: 76311:6a77697d2a63 user: Brett Cannon date: Sat Apr 14 21:18:48 2012 -0400 summary: Rebuild importlib.h to incorporate added comments. files: Python/importlib.h | 60 +++++++++++++++++----------------- 1 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h @@ -2171,9 +2171,9 @@ 111,111,116,115,116,114,97,112,62,117,11,0,0,0,102,105, 110,100,95,109,111,100,117,108,101,23,3,0,0,115,58,0, 0,0,0,2,19,1,3,1,25,1,13,1,11,1,15,1, - 10,1,12,2,9,1,9,1,15,2,9,1,6,1,12,1, + 10,1,12,2,9,1,9,1,15,2,9,1,6,2,12,1, 18,1,12,1,22,1,10,1,15,1,12,1,17,2,6,1, - 31,1,22,1,16,1,22,1,12,1,20,1,117,23,0,0, + 31,2,22,1,16,1,22,1,12,1,20,1,117,23,0,0, 0,95,70,105,108,101,70,105,110,100,101,114,46,102,105,110, 100,95,109,111,100,117,108,101,99,1,0,0,0,0,0,0, 0,3,0,0,0,3,0,0,0,67,0,0,0,115,71,0, @@ -2195,7 +2195,7 @@ 0,0,102,110,40,0,0,0,0,40,0,0,0,0,117,29, 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,9,0,0,0,60,103,101,110,101,120,112,114,62,65,3, + 117,9,0,0,0,60,103,101,110,101,120,112,114,62,67,3, 0,0,115,2,0,0,0,6,0,117,42,0,0,0,95,70, 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, 99,97,99,104,101,46,60,108,111,99,97,108,115,62,46,60, @@ -2210,7 +2210,7 @@ 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, - 95,102,105,108,108,95,99,97,99,104,101,58,3,0,0,115, + 95,102,105,108,108,95,99,97,99,104,101,60,3,0,0,115, 8,0,0,0,0,2,9,1,15,3,15,1,117,23,0,0, 0,95,70,105,108,101,70,105,110,100,101,114,46,95,102,105, 108,108,95,99,97,99,104,101,78,40,8,0,0,0,117,8, @@ -2227,7 +2227,7 @@ 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, 98,111,111,116,115,116,114,97,112,62,117,11,0,0,0,95, 70,105,108,101,70,105,110,100,101,114,249,2,0,0,115,10, - 0,0,0,16,7,6,2,12,17,12,4,12,35,117,11,0, + 0,0,0,16,7,6,2,12,17,12,4,12,37,117,11,0, 0,0,95,70,105,108,101,70,105,110,100,101,114,99,1,0, 0,0,0,0,0,0,1,0,0,0,2,0,0,0,66,0, 0,0,115,44,0,0,0,124,0,0,69,101,0,0,90,1, @@ -2246,7 +2246,7 @@ 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, 98,111,111,116,115,116,114,97,112,62,117,8,0,0,0,95, - 95,105,110,105,116,95,95,73,3,0,0,115,2,0,0,0, + 95,105,110,105,116,95,95,75,3,0,0,115,2,0,0,0, 0,1,117,29,0,0,0,95,83,111,117,114,99,101,70,105, 110,100,101,114,68,101,116,97,105,108,115,46,95,95,105,110, 105,116,95,95,78,84,40,8,0,0,0,117,8,0,0,0, @@ -2262,7 +2262,7 @@ 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, 116,114,97,112,62,117,20,0,0,0,95,83,111,117,114,99, - 101,70,105,110,100,101,114,68,101,116,97,105,108,115,68,3, + 101,70,105,110,100,101,114,68,101,116,97,105,108,115,70,3, 0,0,115,6,0,0,0,16,2,6,1,6,2,117,20,0, 0,0,95,83,111,117,114,99,101,70,105,110,100,101,114,68, 101,116,97,105,108,115,99,1,0,0,0,0,0,0,0,1, @@ -2283,7 +2283,7 @@ 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, 111,111,116,115,116,114,97,112,62,117,8,0,0,0,95,95, - 105,110,105,116,95,95,81,3,0,0,115,2,0,0,0,0, + 105,110,105,116,95,95,83,3,0,0,115,2,0,0,0,0, 1,117,33,0,0,0,95,83,111,117,114,99,101,108,101,115, 115,70,105,110,100,101,114,68,101,116,97,105,108,115,46,95, 95,105,110,105,116,95,95,78,84,40,8,0,0,0,117,8, @@ -2300,7 +2300,7 @@ 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, 46,95,98,111,111,116,115,116,114,97,112,62,117,24,0,0, 0,95,83,111,117,114,99,101,108,101,115,115,70,105,110,100, - 101,114,68,101,116,97,105,108,115,76,3,0,0,115,6,0, + 101,114,68,101,116,97,105,108,115,78,3,0,0,115,6,0, 0,0,16,2,6,1,6,2,117,24,0,0,0,95,83,111, 117,114,99,101,108,101,115,115,70,105,110,100,101,114,68,101, 116,97,105,108,115,99,1,0,0,0,0,0,0,0,1,0, @@ -2321,7 +2321,7 @@ 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, 116,115,116,114,97,112,62,117,8,0,0,0,95,95,105,110, - 105,116,95,95,90,3,0,0,115,2,0,0,0,0,1,117, + 105,116,95,95,92,3,0,0,115,2,0,0,0,0,1,117, 32,0,0,0,95,69,120,116,101,110,115,105,111,110,70,105, 110,100,101,114,68,101,116,97,105,108,115,46,95,95,105,110, 105,116,95,95,78,70,40,8,0,0,0,117,8,0,0,0, @@ -2338,7 +2338,7 @@ 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, 111,111,116,115,116,114,97,112,62,117,23,0,0,0,95,69, 120,116,101,110,115,105,111,110,70,105,110,100,101,114,68,101, - 116,97,105,108,115,85,3,0,0,115,6,0,0,0,16,2, + 116,97,105,108,115,87,3,0,0,115,6,0,0,0,16,2, 6,1,6,2,117,23,0,0,0,95,69,120,116,101,110,115, 105,111,110,70,105,110,100,101,114,68,101,116,97,105,108,115, 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, @@ -2366,7 +2366,7 @@ 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, 116,115,116,114,97,112,62,117,15,0,0,0,95,102,105,108, - 101,95,112,97,116,104,95,104,111,111,107,96,3,0,0,115, + 101,95,112,97,116,104,95,104,111,111,107,98,3,0,0,115, 10,0,0,0,0,2,12,1,12,1,6,1,10,2,117,15, 0,0,0,95,102,105,108,101,95,112,97,116,104,95,104,111, 111,107,99,1,0,0,0,0,0,0,0,1,0,0,0,4, @@ -2406,7 +2406,7 @@ 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, 117,11,0,0,0,95,112,97,116,104,95,104,111,111,107,115, - 113,3,0,0,115,10,0,0,0,0,3,3,1,20,1,13, + 115,3,0,0,115,10,0,0,0,0,3,3,1,20,1,13, 1,15,1,117,30,0,0,0,95,68,101,102,97,117,108,116, 80,97,116,104,70,105,110,100,101,114,46,95,112,97,116,104, 95,104,111,111,107,115,99,2,0,0,0,0,0,0,0,2, @@ -2428,7 +2428,7 @@ 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,20, 0,0,0,95,112,97,116,104,95,105,109,112,111,114,116,101, - 114,95,99,97,99,104,101,122,3,0,0,115,2,0,0,0, + 114,95,99,97,99,104,101,124,3,0,0,115,2,0,0,0, 0,4,117,39,0,0,0,95,68,101,102,97,117,108,116,80, 97,116,104,70,105,110,100,101,114,46,95,112,97,116,104,95, 105,109,112,111,114,116,101,114,95,99,97,99,104,101,40,7, @@ -2445,7 +2445,7 @@ 95,95,117,29,0,0,0,60,102,114,111,122,101,110,32,105, 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, 114,97,112,62,117,18,0,0,0,95,68,101,102,97,117,108, - 116,80,97,116,104,70,105,110,100,101,114,108,3,0,0,115, + 116,80,97,116,104,70,105,110,100,101,114,110,3,0,0,115, 6,0,0,0,16,3,6,2,24,9,117,18,0,0,0,95, 68,101,102,97,117,108,116,80,97,116,104,70,105,110,100,101, 114,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, @@ -2468,7 +2468,7 @@ 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, 116,114,97,112,62,117,9,0,0,0,95,95,101,110,116,101, - 114,95,95,133,3,0,0,115,2,0,0,0,0,2,117,28, + 114,95,95,135,3,0,0,115,2,0,0,0,0,2,117,28, 0,0,0,95,73,109,112,111,114,116,76,111,99,107,67,111, 110,116,101,120,116,46,95,95,101,110,116,101,114,95,95,99, 4,0,0,0,0,0,0,0,4,0,0,0,1,0,0,0, @@ -2487,7 +2487,7 @@ 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, 97,112,62,117,8,0,0,0,95,95,101,120,105,116,95,95, - 137,3,0,0,115,2,0,0,0,0,2,117,27,0,0,0, + 139,3,0,0,115,2,0,0,0,0,2,117,27,0,0,0, 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, 120,116,46,95,95,101,120,105,116,95,95,78,40,6,0,0, 0,117,8,0,0,0,95,95,110,97,109,101,95,95,117,10, @@ -2500,7 +2500,7 @@ 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, 116,114,97,112,62,117,18,0,0,0,95,73,109,112,111,114, - 116,76,111,99,107,67,111,110,116,101,120,116,129,3,0,0, + 116,76,111,99,107,67,111,110,116,101,120,116,131,3,0,0, 115,6,0,0,0,16,2,6,2,12,4,117,18,0,0,0, 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, 120,116,99,3,0,0,0,0,0,0,0,5,0,0,0,4, @@ -2529,7 +2529,7 @@ 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, 98,111,111,116,115,116,114,97,112,62,117,13,0,0,0,95, - 114,101,115,111,108,118,101,95,110,97,109,101,142,3,0,0, + 114,101,115,111,108,118,101,95,110,97,109,101,144,3,0,0, 115,10,0,0,0,0,2,22,1,18,1,15,1,10,1,117, 13,0,0,0,95,114,101,115,111,108,118,101,95,110,97,109, 101,99,2,0,0,0,0,0,0,0,5,0,0,0,4,0, @@ -2556,7 +2556,7 @@ 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, 97,112,62,117,12,0,0,0,95,102,105,110,100,95,109,111, - 100,117,108,101,151,3,0,0,115,16,0,0,0,0,2,13, + 100,117,108,101,153,3,0,0,115,16,0,0,0,0,2,13, 1,13,1,18,1,12,2,15,1,4,2,21,2,117,12,0, 0,0,95,102,105,110,100,95,109,111,100,117,108,101,99,3, 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, @@ -2600,7 +2600,7 @@ 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, 116,115,116,114,97,112,62,117,13,0,0,0,95,115,97,110, - 105,116,121,95,99,104,101,99,107,166,3,0,0,115,24,0, + 105,116,121,95,99,104,101,99,107,168,3,0,0,115,24,0, 0,0,0,2,15,1,30,1,12,1,15,1,6,1,15,1, 15,1,15,1,6,2,27,1,19,1,117,13,0,0,0,95, 115,97,110,105,116,121,95,99,104,101,99,107,117,20,0,0, @@ -2668,7 +2668,7 @@ 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, 114,97,112,62,117,14,0,0,0,95,102,105,110,100,95,97, - 110,100,95,108,111,97,100,187,3,0,0,115,62,0,0,0, + 110,100,95,108,111,97,100,189,3,0,0,115,62,0,0,0, 0,2,6,1,19,1,6,1,15,1,13,2,15,1,11,2, 13,1,3,1,13,1,13,1,22,1,26,1,15,1,12,1, 30,1,15,2,13,1,19,2,13,1,6,2,13,1,32,2, @@ -2728,7 +2728,7 @@ 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, 97,112,62,117,11,0,0,0,95,103,99,100,95,105,109,112, - 111,114,116,228,3,0,0,115,28,0,0,0,0,9,16,1, + 111,114,116,230,3,0,0,115,28,0,0,0,0,9,16,1, 12,1,21,1,10,1,3,1,13,1,12,1,6,1,9,1, 21,1,8,1,13,1,5,1,117,11,0,0,0,95,103,99, 100,95,105,109,112,111,114,116,99,3,0,0,0,0,0,0, @@ -2772,7 +2772,7 @@ 117,108,101,40,0,0,0,0,117,29,0,0,0,60,102,114, 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, 98,111,111,116,115,116,114,97,112,62,117,9,0,0,0,60, - 103,101,110,101,120,112,114,62,12,4,0,0,115,2,0,0, + 103,101,110,101,120,112,114,62,14,4,0,0,115,2,0,0, 0,6,0,117,35,0,0,0,95,104,97,110,100,108,101,95, 102,114,111,109,108,105,115,116,46,60,108,111,99,97,108,115, 62,46,60,103,101,110,101,120,112,114,62,117,7,0,0,0, @@ -2790,7 +2790,7 @@ 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, 62,117,16,0,0,0,95,104,97,110,100,108,101,95,102,114, - 111,109,108,105,115,116,253,3,0,0,115,22,0,0,0,0, + 111,109,108,105,115,116,255,3,0,0,115,22,0,0,0,0, 10,15,1,27,1,12,1,13,1,19,1,32,1,3,1,29, 1,13,1,12,1,117,16,0,0,0,95,104,97,110,100,108, 101,95,102,114,111,109,108,105,115,116,99,1,0,0,0,0, @@ -2822,7 +2822,7 @@ 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, 116,115,116,114,97,112,62,117,17,0,0,0,95,99,97,108, - 99,95,95,95,112,97,99,107,97,103,101,95,95,20,4,0, + 99,95,95,95,112,97,99,107,97,103,101,95,95,22,4,0, 0,115,12,0,0,0,0,7,15,1,12,1,10,1,12,1, 25,1,117,17,0,0,0,95,99,97,108,99,95,95,95,112, 97,99,107,97,103,101,95,95,99,5,0,0,0,0,0,0, @@ -2886,7 +2886,7 @@ 95,111,102,102,40,0,0,0,0,40,0,0,0,0,117,29, 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,35, + 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,37, 4,0,0,115,24,0,0,0,0,11,12,1,15,2,12,1, 18,1,6,3,12,1,24,1,6,1,4,2,35,1,28,2, 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,99, @@ -2971,7 +2971,7 @@ 111,100,117,108,101,40,0,0,0,0,40,0,0,0,0,117, 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,6,0,0,0,95,115,101,116,117,112,65,4,0,0, + 62,117,6,0,0,0,95,115,101,116,117,112,67,4,0,0, 115,52,0,0,0,0,9,6,1,6,2,19,1,15,1,16, 2,13,1,13,1,15,1,18,2,13,1,20,2,28,1,15, 1,13,1,4,2,3,1,15,2,27,1,9,1,5,1,13, @@ -3004,7 +3004,7 @@ 109,112,111,114,116,40,0,0,0,0,40,0,0,0,0,117, 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,8,0,0,0,95,105,110,115,116,97,108,108,110,4, + 62,117,8,0,0,0,95,105,110,115,116,97,108,108,112,4, 0,0,115,8,0,0,0,0,7,13,1,9,1,9,1,117, 8,0,0,0,95,105,110,115,116,97,108,108,78,40,3,0, 0,0,117,3,0,0,0,119,105,110,117,6,0,0,0,99, @@ -3081,7 +3081,7 @@ 6,12,7,12,9,12,13,12,21,12,8,15,4,12,8,12, 13,12,11,12,32,12,16,12,11,12,11,12,8,19,53,19, 47,19,77,22,114,19,22,25,38,25,24,19,45,19,68,19, - 75,19,8,19,9,19,11,12,10,6,2,22,21,19,13,12, + 77,19,8,19,9,19,11,12,10,6,2,22,21,19,13,12, 9,12,15,12,17,15,2,6,2,12,41,18,25,12,23,12, 15,24,30,12,45, }; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 03:50:08 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 03:50:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Handle_importing_pkg=2Emod_?= =?utf8?q?by_executing?= Message-ID: http://hg.python.org/cpython/rev/9e8cbf07068a changeset: 76312:9e8cbf07068a user: Brett Cannon date: Sat Apr 14 21:50:00 2012 -0400 summary: Handle importing pkg.mod by executing __import__('mod', {'__packaging__': 'pkg', level=1) w/o properly (and thus not segfaulting). files: Lib/importlib/_bootstrap.py | 2 +- Lib/importlib/test/import_/test_relative_imports.py | 9 + Python/import.c | 21 +- Python/importlib.h | 497 +++++---- 4 files changed, 276 insertions(+), 253 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -1083,7 +1083,7 @@ return module else: cut_off = len(name) - len(name.partition('.')[0]) - return sys.modules[module.__name__[:-cut_off]] + return sys.modules[module.__name__[:len(module.__name__)-cut_off]] else: return _handle_fromlist(module, fromlist, _gcd_import) diff --git a/Lib/importlib/test/import_/test_relative_imports.py b/Lib/importlib/test/import_/test_relative_imports.py --- a/Lib/importlib/test/import_/test_relative_imports.py +++ b/Lib/importlib/test/import_/test_relative_imports.py @@ -193,6 +193,15 @@ self.assertEqual(module.__name__, '__runpy_pkg__.uncle.cousin') self.relative_import_test(create, globals_, callback) + def test_import_relative_import_no_fromlist(self): + # Import a relative module w/ no fromlist. + create = ['crash.__init__', 'crash.mod'] + globals_ = [{'__package__': 'crash', '__name__': 'crash'}] + def callback(global_): + import_util.import_('crash') + mod = import_util.import_('mod', global_, {}, [], 1) + self.assertEqual(mod.__name__, 'crash.mod') + self.relative_import_test(create, globals_, callback) def test_main(): diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -3016,20 +3016,33 @@ Py_DECREF(partition); if (level == 0) { - final_mod = PyDict_GetItemWithError(interp->modules, front); + final_mod = PyDict_GetItem(interp->modules, front); Py_DECREF(front); - Py_XINCREF(final_mod); + if (final_mod == NULL) { + PyErr_Format(PyExc_KeyError, + "%R not in sys.modules as expected", front); + } + else { + Py_INCREF(final_mod); + } } else { Py_ssize_t cut_off = PyUnicode_GetLength(name) - PyUnicode_GetLength(front); Py_ssize_t abs_name_len = PyUnicode_GetLength(abs_name); - PyObject *to_return = PyUnicode_Substring(name, 0, + PyObject *to_return = PyUnicode_Substring(abs_name, 0, abs_name_len - cut_off); final_mod = PyDict_GetItem(interp->modules, to_return); - Py_INCREF(final_mod); Py_DECREF(to_return); + if (final_mod == NULL) { + PyErr_Format(PyExc_KeyError, + "%R not in sys.modules as expected", + to_return); + } + else { + Py_INCREF(final_mod); + } } } else { diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h @@ -2826,262 +2826,263 @@ 0,115,12,0,0,0,0,7,15,1,12,1,10,1,12,1, 25,1,117,17,0,0,0,95,99,97,108,99,95,95,95,112, 97,99,107,97,103,101,95,95,99,5,0,0,0,0,0,0, - 0,8,0,0,0,4,0,0,0,67,0,0,0,115,192,0, + 0,8,0,0,0,5,0,0,0,67,0,0,0,115,204,0, 0,0,124,4,0,100,1,0,107,2,0,114,27,0,116,0, 0,124,0,0,131,1,0,125,5,0,110,30,0,116,1,0, 124,1,0,131,1,0,125,6,0,116,0,0,124,0,0,124, - 6,0,124,4,0,131,3,0,125,5,0,124,3,0,115,172, + 6,0,124,4,0,131,3,0,125,5,0,124,3,0,115,184, 0,124,4,0,100,1,0,107,2,0,114,99,0,116,2,0, 106,3,0,124,0,0,106,4,0,100,2,0,131,1,0,100, 1,0,25,25,83,124,0,0,115,109,0,124,5,0,83,116, 5,0,124,0,0,131,1,0,116,5,0,124,0,0,106,4, 0,100,2,0,131,1,0,100,1,0,25,131,1,0,24,125, 7,0,116,2,0,106,3,0,124,5,0,106,6,0,100,3, - 0,124,7,0,11,133,2,0,25,25,83,110,16,0,116,7, - 0,124,5,0,124,3,0,116,0,0,131,3,0,83,100,3, - 0,83,40,4,0,0,0,117,214,1,0,0,73,109,112,111, - 114,116,32,97,32,109,111,100,117,108,101,46,10,10,32,32, - 32,32,84,104,101,32,39,103,108,111,98,97,108,115,39,32, - 97,114,103,117,109,101,110,116,32,105,115,32,117,115,101,100, - 32,116,111,32,105,110,102,101,114,32,119,104,101,114,101,32, - 116,104,101,32,105,109,112,111,114,116,32,105,115,32,111,99, - 99,117,114,105,110,103,32,102,114,111,109,10,32,32,32,32, - 116,111,32,104,97,110,100,108,101,32,114,101,108,97,116,105, - 118,101,32,105,109,112,111,114,116,115,46,32,84,104,101,32, - 39,108,111,99,97,108,115,39,32,97,114,103,117,109,101,110, - 116,32,105,115,32,105,103,110,111,114,101,100,46,32,84,104, - 101,10,32,32,32,32,39,102,114,111,109,108,105,115,116,39, - 32,97,114,103,117,109,101,110,116,32,115,112,101,99,105,102, - 105,101,115,32,119,104,97,116,32,115,104,111,117,108,100,32, - 101,120,105,115,116,32,97,115,32,97,116,116,114,105,98,117, - 116,101,115,32,111,110,32,116,104,101,32,109,111,100,117,108, - 101,10,32,32,32,32,98,101,105,110,103,32,105,109,112,111, - 114,116,101,100,32,40,101,46,103,46,32,96,96,102,114,111, - 109,32,109,111,100,117,108,101,32,105,109,112,111,114,116,32, - 60,102,114,111,109,108,105,115,116,62,96,96,41,46,32,32, - 84,104,101,32,39,108,101,118,101,108,39,10,32,32,32,32, - 97,114,103,117,109,101,110,116,32,114,101,112,114,101,115,101, - 110,116,115,32,116,104,101,32,112,97,99,107,97,103,101,32, - 108,111,99,97,116,105,111,110,32,116,111,32,105,109,112,111, - 114,116,32,102,114,111,109,32,105,110,32,97,32,114,101,108, - 97,116,105,118,101,10,32,32,32,32,105,109,112,111,114,116, - 32,40,101,46,103,46,32,96,96,102,114,111,109,32,46,46, - 112,107,103,32,105,109,112,111,114,116,32,109,111,100,96,96, - 32,119,111,117,108,100,32,104,97,118,101,32,97,32,39,108, - 101,118,101,108,39,32,111,102,32,50,41,46,10,10,32,32, - 32,32,105,0,0,0,0,117,1,0,0,0,46,78,40,8, - 0,0,0,117,11,0,0,0,95,103,99,100,95,105,109,112, - 111,114,116,117,17,0,0,0,95,99,97,108,99,95,95,95, - 112,97,99,107,97,103,101,95,95,117,3,0,0,0,115,121, - 115,117,7,0,0,0,109,111,100,117,108,101,115,117,9,0, - 0,0,112,97,114,116,105,116,105,111,110,117,3,0,0,0, - 108,101,110,117,8,0,0,0,95,95,110,97,109,101,95,95, - 117,16,0,0,0,95,104,97,110,100,108,101,95,102,114,111, - 109,108,105,115,116,40,8,0,0,0,117,4,0,0,0,110, - 97,109,101,117,7,0,0,0,103,108,111,98,97,108,115,117, - 6,0,0,0,108,111,99,97,108,115,117,8,0,0,0,102, - 114,111,109,108,105,115,116,117,5,0,0,0,108,101,118,101, - 108,117,6,0,0,0,109,111,100,117,108,101,117,7,0,0, - 0,112,97,99,107,97,103,101,117,7,0,0,0,99,117,116, - 95,111,102,102,40,0,0,0,0,40,0,0,0,0,117,29, - 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,37, - 4,0,0,115,24,0,0,0,0,11,12,1,15,2,12,1, - 18,1,6,3,12,1,24,1,6,1,4,2,35,1,28,2, - 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,99, - 2,0,0,0,0,0,0,0,9,0,0,0,12,0,0,0, - 67,0,0,0,115,109,1,0,0,124,1,0,97,0,0,124, - 0,0,97,1,0,120,47,0,116,0,0,116,1,0,102,2, - 0,68,93,33,0,125,2,0,116,2,0,124,2,0,100,1, - 0,131,2,0,115,25,0,116,3,0,124,2,0,95,4,0, - 113,25,0,113,25,0,87,116,1,0,106,5,0,116,6,0, - 25,125,3,0,120,76,0,100,17,0,68,93,68,0,125,4, - 0,124,4,0,116,1,0,106,5,0,107,7,0,114,121,0, - 116,3,0,106,7,0,124,4,0,131,1,0,125,5,0,110, - 13,0,116,1,0,106,5,0,124,4,0,25,125,5,0,116, - 8,0,124,3,0,124,4,0,124,5,0,131,3,0,1,113, - 82,0,87,120,153,0,100,18,0,100,19,0,100,20,0,103, - 3,0,68,93,124,0,92,2,0,125,6,0,125,7,0,124, - 6,0,116,1,0,106,5,0,107,6,0,114,214,0,116,1, - 0,106,5,0,124,6,0,25,125,8,0,80,113,170,0,121, - 56,0,116,3,0,106,7,0,124,6,0,131,1,0,125,8, - 0,124,6,0,100,10,0,107,2,0,114,12,1,100,11,0, - 116,1,0,106,9,0,107,6,0,114,12,1,100,7,0,125, - 7,0,110,0,0,80,87,113,170,0,4,116,10,0,107,10, - 0,114,37,1,1,1,1,119,170,0,89,113,170,0,88,113, - 170,0,87,116,10,0,100,12,0,131,1,0,130,1,0,116, - 8,0,124,3,0,100,13,0,124,8,0,131,3,0,1,116, - 8,0,124,3,0,100,14,0,124,7,0,131,3,0,1,116, - 8,0,124,3,0,100,15,0,116,11,0,131,0,0,131,3, - 0,1,100,16,0,83,40,21,0,0,0,117,249,0,0,0, - 83,101,116,117,112,32,105,109,112,111,114,116,108,105,98,32, - 98,121,32,105,109,112,111,114,116,105,110,103,32,110,101,101, - 100,101,100,32,98,117,105,108,116,45,105,110,32,109,111,100, - 117,108,101,115,32,97,110,100,32,105,110,106,101,99,116,105, - 110,103,32,116,104,101,109,10,32,32,32,32,105,110,116,111, - 32,116,104,101,32,103,108,111,98,97,108,32,110,97,109,101, - 115,112,97,99,101,46,10,10,32,32,32,32,65,115,32,115, - 121,115,32,105,115,32,110,101,101,100,101,100,32,102,111,114, - 32,115,121,115,46,109,111,100,117,108,101,115,32,97,99,99, - 101,115,115,32,97,110,100,32,105,109,112,32,105,115,32,110, - 101,101,100,101,100,32,116,111,32,108,111,97,100,32,98,117, - 105,108,116,45,105,110,10,32,32,32,32,109,111,100,117,108, - 101,115,44,32,116,104,111,115,101,32,116,119,111,32,109,111, - 100,117,108,101,115,32,109,117,115,116,32,98,101,32,101,120, - 112,108,105,99,105,116,108,121,32,112,97,115,115,101,100,32, - 105,110,46,10,10,32,32,32,32,117,10,0,0,0,95,95, - 108,111,97,100,101,114,95,95,117,3,0,0,0,95,105,111, - 117,9,0,0,0,95,119,97,114,110,105,110,103,115,117,8, - 0,0,0,98,117,105,108,116,105,110,115,117,7,0,0,0, - 109,97,114,115,104,97,108,117,5,0,0,0,112,111,115,105, - 120,117,1,0,0,0,47,117,2,0,0,0,110,116,117,1, - 0,0,0,92,117,3,0,0,0,111,115,50,117,7,0,0, - 0,69,77,88,32,71,67,67,117,30,0,0,0,105,109,112, - 111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,32, - 112,111,115,105,120,32,111,114,32,110,116,117,3,0,0,0, - 95,111,115,117,8,0,0,0,112,97,116,104,95,115,101,112, - 117,11,0,0,0,95,114,101,108,97,120,95,99,97,115,101, - 78,40,4,0,0,0,117,3,0,0,0,95,105,111,117,9, - 0,0,0,95,119,97,114,110,105,110,103,115,117,8,0,0, - 0,98,117,105,108,116,105,110,115,117,7,0,0,0,109,97, - 114,115,104,97,108,40,2,0,0,0,117,5,0,0,0,112, - 111,115,105,120,117,1,0,0,0,47,40,2,0,0,0,117, - 2,0,0,0,110,116,117,1,0,0,0,92,40,2,0,0, - 0,117,3,0,0,0,111,115,50,117,1,0,0,0,92,40, - 12,0,0,0,117,3,0,0,0,105,109,112,117,3,0,0, - 0,115,121,115,117,7,0,0,0,104,97,115,97,116,116,114, - 117,15,0,0,0,66,117,105,108,116,105,110,73,109,112,111, - 114,116,101,114,117,10,0,0,0,95,95,108,111,97,100,101, - 114,95,95,117,7,0,0,0,109,111,100,117,108,101,115,117, - 8,0,0,0,95,95,110,97,109,101,95,95,117,11,0,0, - 0,108,111,97,100,95,109,111,100,117,108,101,117,7,0,0, - 0,115,101,116,97,116,116,114,117,7,0,0,0,118,101,114, - 115,105,111,110,117,11,0,0,0,73,109,112,111,114,116,69, - 114,114,111,114,117,16,0,0,0,95,109,97,107,101,95,114, - 101,108,97,120,95,99,97,115,101,40,9,0,0,0,117,10, - 0,0,0,115,121,115,95,109,111,100,117,108,101,117,10,0, - 0,0,105,109,112,95,109,111,100,117,108,101,117,6,0,0, - 0,109,111,100,117,108,101,117,11,0,0,0,115,101,108,102, - 95,109,111,100,117,108,101,117,12,0,0,0,98,117,105,108, - 116,105,110,95,110,97,109,101,117,14,0,0,0,98,117,105, - 108,116,105,110,95,109,111,100,117,108,101,117,10,0,0,0, - 98,117,105,108,116,105,110,95,111,115,117,8,0,0,0,112, - 97,116,104,95,115,101,112,117,9,0,0,0,111,115,95,109, - 111,100,117,108,101,40,0,0,0,0,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,6,0,0,0,95,115,101,116,117,112,67,4,0,0, - 115,52,0,0,0,0,9,6,1,6,2,19,1,15,1,16, - 2,13,1,13,1,15,1,18,2,13,1,20,2,28,1,15, - 1,13,1,4,2,3,1,15,2,27,1,9,1,5,1,13, - 1,12,2,12,1,16,1,16,2,117,6,0,0,0,95,115, - 101,116,117,112,99,2,0,0,0,0,0,0,0,3,0,0, - 0,3,0,0,0,67,0,0,0,115,44,0,0,0,116,0, - 0,124,0,0,124,1,0,131,2,0,1,116,1,0,106,2, - 0,125,2,0,116,2,0,116,1,0,95,2,0,124,2,0, - 116,1,0,95,3,0,100,1,0,83,40,2,0,0,0,117, - 201,0,0,0,73,110,115,116,97,108,108,32,105,109,112,111, - 114,116,108,105,98,32,97,115,32,116,104,101,32,105,109,112, - 108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,105, - 109,112,111,114,116,46,10,10,32,32,32,32,73,116,32,105, - 115,32,97,115,115,117,109,101,100,32,116,104,97,116,32,105, - 109,112,32,97,110,100,32,115,121,115,32,104,97,118,101,32, - 98,101,101,110,32,105,109,112,111,114,116,101,100,32,97,110, - 100,32,105,110,106,101,99,116,101,100,32,105,110,116,111,32, - 116,104,101,10,32,32,32,32,103,108,111,98,97,108,32,110, - 97,109,101,115,112,97,99,101,32,102,111,114,32,116,104,101, - 32,109,111,100,117,108,101,32,112,114,105,111,114,32,116,111, - 32,99,97,108,108,105,110,103,32,116,104,105,115,32,102,117, - 110,99,116,105,111,110,46,10,10,32,32,32,32,78,40,4, - 0,0,0,117,6,0,0,0,95,115,101,116,117,112,117,8, - 0,0,0,98,117,105,108,116,105,110,115,117,10,0,0,0, - 95,95,105,109,112,111,114,116,95,95,117,19,0,0,0,95, - 95,111,114,105,103,105,110,97,108,95,105,109,112,111,114,116, - 95,95,40,3,0,0,0,117,10,0,0,0,115,121,115,95, - 109,111,100,117,108,101,117,10,0,0,0,105,109,112,95,109, - 111,100,117,108,101,117,11,0,0,0,111,114,105,103,95,105, - 109,112,111,114,116,40,0,0,0,0,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,8,0,0,0,95,105,110,115,116,97,108,108,112,4, - 0,0,115,8,0,0,0,0,7,13,1,9,1,9,1,117, - 8,0,0,0,95,105,110,115,116,97,108,108,78,40,3,0, - 0,0,117,3,0,0,0,119,105,110,117,6,0,0,0,99, - 121,103,119,105,110,117,6,0,0,0,100,97,114,119,105,110, - 40,55,0,0,0,117,7,0,0,0,95,95,100,111,99,95, - 95,117,26,0,0,0,67,65,83,69,95,73,78,83,69,78, - 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, + 0,116,5,0,124,5,0,106,6,0,131,1,0,124,7,0, + 24,133,2,0,25,25,83,110,16,0,116,7,0,124,5,0, + 124,3,0,116,0,0,131,3,0,83,100,3,0,83,40,4, + 0,0,0,117,214,1,0,0,73,109,112,111,114,116,32,97, + 32,109,111,100,117,108,101,46,10,10,32,32,32,32,84,104, + 101,32,39,103,108,111,98,97,108,115,39,32,97,114,103,117, + 109,101,110,116,32,105,115,32,117,115,101,100,32,116,111,32, + 105,110,102,101,114,32,119,104,101,114,101,32,116,104,101,32, + 105,109,112,111,114,116,32,105,115,32,111,99,99,117,114,105, + 110,103,32,102,114,111,109,10,32,32,32,32,116,111,32,104, + 97,110,100,108,101,32,114,101,108,97,116,105,118,101,32,105, + 109,112,111,114,116,115,46,32,84,104,101,32,39,108,111,99, + 97,108,115,39,32,97,114,103,117,109,101,110,116,32,105,115, + 32,105,103,110,111,114,101,100,46,32,84,104,101,10,32,32, + 32,32,39,102,114,111,109,108,105,115,116,39,32,97,114,103, + 117,109,101,110,116,32,115,112,101,99,105,102,105,101,115,32, + 119,104,97,116,32,115,104,111,117,108,100,32,101,120,105,115, + 116,32,97,115,32,97,116,116,114,105,98,117,116,101,115,32, + 111,110,32,116,104,101,32,109,111,100,117,108,101,10,32,32, + 32,32,98,101,105,110,103,32,105,109,112,111,114,116,101,100, + 32,40,101,46,103,46,32,96,96,102,114,111,109,32,109,111, + 100,117,108,101,32,105,109,112,111,114,116,32,60,102,114,111, + 109,108,105,115,116,62,96,96,41,46,32,32,84,104,101,32, + 39,108,101,118,101,108,39,10,32,32,32,32,97,114,103,117, + 109,101,110,116,32,114,101,112,114,101,115,101,110,116,115,32, + 116,104,101,32,112,97,99,107,97,103,101,32,108,111,99,97, + 116,105,111,110,32,116,111,32,105,109,112,111,114,116,32,102, + 114,111,109,32,105,110,32,97,32,114,101,108,97,116,105,118, + 101,10,32,32,32,32,105,109,112,111,114,116,32,40,101,46, + 103,46,32,96,96,102,114,111,109,32,46,46,112,107,103,32, + 105,109,112,111,114,116,32,109,111,100,96,96,32,119,111,117, + 108,100,32,104,97,118,101,32,97,32,39,108,101,118,101,108, + 39,32,111,102,32,50,41,46,10,10,32,32,32,32,105,0, + 0,0,0,117,1,0,0,0,46,78,40,8,0,0,0,117, + 11,0,0,0,95,103,99,100,95,105,109,112,111,114,116,117, + 17,0,0,0,95,99,97,108,99,95,95,95,112,97,99,107, + 97,103,101,95,95,117,3,0,0,0,115,121,115,117,7,0, + 0,0,109,111,100,117,108,101,115,117,9,0,0,0,112,97, + 114,116,105,116,105,111,110,117,3,0,0,0,108,101,110,117, + 8,0,0,0,95,95,110,97,109,101,95,95,117,16,0,0, + 0,95,104,97,110,100,108,101,95,102,114,111,109,108,105,115, + 116,40,8,0,0,0,117,4,0,0,0,110,97,109,101,117, + 7,0,0,0,103,108,111,98,97,108,115,117,6,0,0,0, + 108,111,99,97,108,115,117,8,0,0,0,102,114,111,109,108, + 105,115,116,117,5,0,0,0,108,101,118,101,108,117,6,0, + 0,0,109,111,100,117,108,101,117,7,0,0,0,112,97,99, + 107,97,103,101,117,7,0,0,0,99,117,116,95,111,102,102, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, + 0,95,95,105,109,112,111,114,116,95,95,37,4,0,0,115, + 24,0,0,0,0,11,12,1,15,2,12,1,18,1,6,3, + 12,1,24,1,6,1,4,2,35,1,40,2,117,10,0,0, + 0,95,95,105,109,112,111,114,116,95,95,99,2,0,0,0, + 0,0,0,0,9,0,0,0,12,0,0,0,67,0,0,0, + 115,109,1,0,0,124,1,0,97,0,0,124,0,0,97,1, + 0,120,47,0,116,0,0,116,1,0,102,2,0,68,93,33, + 0,125,2,0,116,2,0,124,2,0,100,1,0,131,2,0, + 115,25,0,116,3,0,124,2,0,95,4,0,113,25,0,113, + 25,0,87,116,1,0,106,5,0,116,6,0,25,125,3,0, + 120,76,0,100,17,0,68,93,68,0,125,4,0,124,4,0, + 116,1,0,106,5,0,107,7,0,114,121,0,116,3,0,106, + 7,0,124,4,0,131,1,0,125,5,0,110,13,0,116,1, + 0,106,5,0,124,4,0,25,125,5,0,116,8,0,124,3, + 0,124,4,0,124,5,0,131,3,0,1,113,82,0,87,120, + 153,0,100,18,0,100,19,0,100,20,0,103,3,0,68,93, + 124,0,92,2,0,125,6,0,125,7,0,124,6,0,116,1, + 0,106,5,0,107,6,0,114,214,0,116,1,0,106,5,0, + 124,6,0,25,125,8,0,80,113,170,0,121,56,0,116,3, + 0,106,7,0,124,6,0,131,1,0,125,8,0,124,6,0, + 100,10,0,107,2,0,114,12,1,100,11,0,116,1,0,106, + 9,0,107,6,0,114,12,1,100,7,0,125,7,0,110,0, + 0,80,87,113,170,0,4,116,10,0,107,10,0,114,37,1, + 1,1,1,119,170,0,89,113,170,0,88,113,170,0,87,116, + 10,0,100,12,0,131,1,0,130,1,0,116,8,0,124,3, + 0,100,13,0,124,8,0,131,3,0,1,116,8,0,124,3, + 0,100,14,0,124,7,0,131,3,0,1,116,8,0,124,3, + 0,100,15,0,116,11,0,131,0,0,131,3,0,1,100,16, + 0,83,40,21,0,0,0,117,249,0,0,0,83,101,116,117, + 112,32,105,109,112,111,114,116,108,105,98,32,98,121,32,105, + 109,112,111,114,116,105,110,103,32,110,101,101,100,101,100,32, + 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,115, + 32,97,110,100,32,105,110,106,101,99,116,105,110,103,32,116, + 104,101,109,10,32,32,32,32,105,110,116,111,32,116,104,101, + 32,103,108,111,98,97,108,32,110,97,109,101,115,112,97,99, + 101,46,10,10,32,32,32,32,65,115,32,115,121,115,32,105, + 115,32,110,101,101,100,101,100,32,102,111,114,32,115,121,115, + 46,109,111,100,117,108,101,115,32,97,99,99,101,115,115,32, + 97,110,100,32,105,109,112,32,105,115,32,110,101,101,100,101, + 100,32,116,111,32,108,111,97,100,32,98,117,105,108,116,45, + 105,110,10,32,32,32,32,109,111,100,117,108,101,115,44,32, + 116,104,111,115,101,32,116,119,111,32,109,111,100,117,108,101, + 115,32,109,117,115,116,32,98,101,32,101,120,112,108,105,99, + 105,116,108,121,32,112,97,115,115,101,100,32,105,110,46,10, + 10,32,32,32,32,117,10,0,0,0,95,95,108,111,97,100, + 101,114,95,95,117,3,0,0,0,95,105,111,117,9,0,0, + 0,95,119,97,114,110,105,110,103,115,117,8,0,0,0,98, + 117,105,108,116,105,110,115,117,7,0,0,0,109,97,114,115, + 104,97,108,117,5,0,0,0,112,111,115,105,120,117,1,0, + 0,0,47,117,2,0,0,0,110,116,117,1,0,0,0,92, + 117,3,0,0,0,111,115,50,117,7,0,0,0,69,77,88, + 32,71,67,67,117,30,0,0,0,105,109,112,111,114,116,108, + 105,98,32,114,101,113,117,105,114,101,115,32,112,111,115,105, + 120,32,111,114,32,110,116,117,3,0,0,0,95,111,115,117, + 8,0,0,0,112,97,116,104,95,115,101,112,117,11,0,0, + 0,95,114,101,108,97,120,95,99,97,115,101,78,40,4,0, + 0,0,117,3,0,0,0,95,105,111,117,9,0,0,0,95, + 119,97,114,110,105,110,103,115,117,8,0,0,0,98,117,105, + 108,116,105,110,115,117,7,0,0,0,109,97,114,115,104,97, + 108,40,2,0,0,0,117,5,0,0,0,112,111,115,105,120, + 117,1,0,0,0,47,40,2,0,0,0,117,2,0,0,0, + 110,116,117,1,0,0,0,92,40,2,0,0,0,117,3,0, + 0,0,111,115,50,117,1,0,0,0,92,40,12,0,0,0, + 117,3,0,0,0,105,109,112,117,3,0,0,0,115,121,115, + 117,7,0,0,0,104,97,115,97,116,116,114,117,15,0,0, + 0,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, + 117,10,0,0,0,95,95,108,111,97,100,101,114,95,95,117, + 7,0,0,0,109,111,100,117,108,101,115,117,8,0,0,0, + 95,95,110,97,109,101,95,95,117,11,0,0,0,108,111,97, + 100,95,109,111,100,117,108,101,117,7,0,0,0,115,101,116, + 97,116,116,114,117,7,0,0,0,118,101,114,115,105,111,110, + 117,11,0,0,0,73,109,112,111,114,116,69,114,114,111,114, 117,16,0,0,0,95,109,97,107,101,95,114,101,108,97,120, - 95,99,97,115,101,117,7,0,0,0,95,119,95,108,111,110, - 103,117,7,0,0,0,95,114,95,108,111,110,103,117,10,0, - 0,0,95,112,97,116,104,95,106,111,105,110,117,12,0,0, - 0,95,112,97,116,104,95,101,120,105,115,116,115,117,18,0, - 0,0,95,112,97,116,104,95,105,115,95,109,111,100,101,95, - 116,121,112,101,117,12,0,0,0,95,112,97,116,104,95,105, - 115,102,105,108,101,117,11,0,0,0,95,112,97,116,104,95, - 105,115,100,105,114,117,17,0,0,0,95,112,97,116,104,95, - 119,105,116,104,111,117,116,95,101,120,116,117,14,0,0,0, - 95,112,97,116,104,95,97,98,115,111,108,117,116,101,117,13, - 0,0,0,95,119,114,105,116,101,95,97,116,111,109,105,99, - 117,5,0,0,0,95,119,114,97,112,117,4,0,0,0,116, - 121,112,101,117,8,0,0,0,95,95,99,111,100,101,95,95, - 117,9,0,0,0,99,111,100,101,95,116,121,112,101,117,15, - 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, - 103,101,117,11,0,0,0,115,101,116,95,112,97,99,107,97, - 103,101,117,10,0,0,0,115,101,116,95,108,111,97,100,101, - 114,117,17,0,0,0,109,111,100,117,108,101,95,102,111,114, - 95,108,111,97,100,101,114,117,11,0,0,0,95,99,104,101, - 99,107,95,110,97,109,101,117,17,0,0,0,95,114,101,113, - 117,105,114,101,115,95,98,117,105,108,116,105,110,117,16,0, - 0,0,95,114,101,113,117,105,114,101,115,95,102,114,111,122, - 101,110,117,12,0,0,0,95,115,117,102,102,105,120,95,108, - 105,115,116,117,15,0,0,0,66,117,105,108,116,105,110,73, - 109,112,111,114,116,101,114,117,14,0,0,0,70,114,111,122, - 101,110,73,109,112,111,114,116,101,114,117,13,0,0,0,95, - 76,111,97,100,101,114,66,97,115,105,99,115,117,12,0,0, - 0,83,111,117,114,99,101,76,111,97,100,101,114,117,11,0, - 0,0,95,70,105,108,101,76,111,97,100,101,114,117,17,0, - 0,0,95,83,111,117,114,99,101,70,105,108,101,76,111,97, - 100,101,114,117,21,0,0,0,95,83,111,117,114,99,101,108, - 101,115,115,70,105,108,101,76,111,97,100,101,114,117,20,0, - 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,117,10,0,0,0,80,97,116,104,70, - 105,110,100,101,114,117,11,0,0,0,95,70,105,108,101,70, - 105,110,100,101,114,117,20,0,0,0,95,83,111,117,114,99, - 101,70,105,110,100,101,114,68,101,116,97,105,108,115,117,24, - 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, - 110,100,101,114,68,101,116,97,105,108,115,117,23,0,0,0, - 95,69,120,116,101,110,115,105,111,110,70,105,110,100,101,114, - 68,101,116,97,105,108,115,117,15,0,0,0,95,102,105,108, - 101,95,112,97,116,104,95,104,111,111,107,117,18,0,0,0, - 95,68,69,70,65,85,76,84,95,80,65,84,72,95,72,79, - 79,75,117,18,0,0,0,95,68,101,102,97,117,108,116,80, - 97,116,104,70,105,110,100,101,114,117,18,0,0,0,95,73, - 109,112,111,114,116,76,111,99,107,67,111,110,116,101,120,116, - 117,13,0,0,0,95,114,101,115,111,108,118,101,95,110,97, - 109,101,117,12,0,0,0,95,102,105,110,100,95,109,111,100, - 117,108,101,117,13,0,0,0,95,115,97,110,105,116,121,95, - 99,104,101,99,107,117,19,0,0,0,95,73,77,80,76,73, - 67,73,84,95,77,69,84,65,95,80,65,84,72,117,8,0, - 0,0,95,69,82,82,95,77,83,71,117,14,0,0,0,95, - 102,105,110,100,95,97,110,100,95,108,111,97,100,117,4,0, - 0,0,78,111,110,101,117,11,0,0,0,95,103,99,100,95, - 105,109,112,111,114,116,117,16,0,0,0,95,104,97,110,100, - 108,101,95,102,114,111,109,108,105,115,116,117,17,0,0,0, - 95,99,97,108,99,95,95,95,112,97,99,107,97,103,101,95, - 95,117,10,0,0,0,95,95,105,109,112,111,114,116,95,95, - 117,6,0,0,0,95,115,101,116,117,112,117,8,0,0,0, - 95,105,110,115,116,97,108,108,40,0,0,0,0,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,8,0,0,0,60,109, - 111,100,117,108,101,62,8,0,0,0,115,102,0,0,0,6, - 14,6,3,12,13,12,16,12,15,12,6,12,10,12,10,12, - 6,12,7,12,9,12,13,12,21,12,8,15,4,12,8,12, - 13,12,11,12,32,12,16,12,11,12,11,12,8,19,53,19, - 47,19,77,22,114,19,22,25,38,25,24,19,45,19,68,19, - 77,19,8,19,9,19,11,12,10,6,2,22,21,19,13,12, - 9,12,15,12,17,15,2,6,2,12,41,18,25,12,23,12, - 15,24,30,12,45, + 95,99,97,115,101,40,9,0,0,0,117,10,0,0,0,115, + 121,115,95,109,111,100,117,108,101,117,10,0,0,0,105,109, + 112,95,109,111,100,117,108,101,117,6,0,0,0,109,111,100, + 117,108,101,117,11,0,0,0,115,101,108,102,95,109,111,100, + 117,108,101,117,12,0,0,0,98,117,105,108,116,105,110,95, + 110,97,109,101,117,14,0,0,0,98,117,105,108,116,105,110, + 95,109,111,100,117,108,101,117,10,0,0,0,98,117,105,108, + 116,105,110,95,111,115,117,8,0,0,0,112,97,116,104,95, + 115,101,112,117,9,0,0,0,111,115,95,109,111,100,117,108, + 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,6,0, + 0,0,95,115,101,116,117,112,67,4,0,0,115,52,0,0, + 0,0,9,6,1,6,2,19,1,15,1,16,2,13,1,13, + 1,15,1,18,2,13,1,20,2,28,1,15,1,13,1,4, + 2,3,1,15,2,27,1,9,1,5,1,13,1,12,2,12, + 1,16,1,16,2,117,6,0,0,0,95,115,101,116,117,112, + 99,2,0,0,0,0,0,0,0,3,0,0,0,3,0,0, + 0,67,0,0,0,115,44,0,0,0,116,0,0,124,0,0, + 124,1,0,131,2,0,1,116,1,0,106,2,0,125,2,0, + 116,2,0,116,1,0,95,2,0,124,2,0,116,1,0,95, + 3,0,100,1,0,83,40,2,0,0,0,117,201,0,0,0, + 73,110,115,116,97,108,108,32,105,109,112,111,114,116,108,105, + 98,32,97,115,32,116,104,101,32,105,109,112,108,101,109,101, + 110,116,97,116,105,111,110,32,111,102,32,105,109,112,111,114, + 116,46,10,10,32,32,32,32,73,116,32,105,115,32,97,115, + 115,117,109,101,100,32,116,104,97,116,32,105,109,112,32,97, + 110,100,32,115,121,115,32,104,97,118,101,32,98,101,101,110, + 32,105,109,112,111,114,116,101,100,32,97,110,100,32,105,110, + 106,101,99,116,101,100,32,105,110,116,111,32,116,104,101,10, + 32,32,32,32,103,108,111,98,97,108,32,110,97,109,101,115, + 112,97,99,101,32,102,111,114,32,116,104,101,32,109,111,100, + 117,108,101,32,112,114,105,111,114,32,116,111,32,99,97,108, + 108,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105, + 111,110,46,10,10,32,32,32,32,78,40,4,0,0,0,117, + 6,0,0,0,95,115,101,116,117,112,117,8,0,0,0,98, + 117,105,108,116,105,110,115,117,10,0,0,0,95,95,105,109, + 112,111,114,116,95,95,117,19,0,0,0,95,95,111,114,105, + 103,105,110,97,108,95,105,109,112,111,114,116,95,95,40,3, + 0,0,0,117,10,0,0,0,115,121,115,95,109,111,100,117, + 108,101,117,10,0,0,0,105,109,112,95,109,111,100,117,108, + 101,117,11,0,0,0,111,114,105,103,95,105,109,112,111,114, + 116,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, + 0,0,95,105,110,115,116,97,108,108,112,4,0,0,115,8, + 0,0,0,0,7,13,1,9,1,9,1,117,8,0,0,0, + 95,105,110,115,116,97,108,108,78,40,3,0,0,0,117,3, + 0,0,0,119,105,110,117,6,0,0,0,99,121,103,119,105, + 110,117,6,0,0,0,100,97,114,119,105,110,40,55,0,0, + 0,117,7,0,0,0,95,95,100,111,99,95,95,117,26,0, + 0,0,67,65,83,69,95,73,78,83,69,78,83,73,84,73, + 86,69,95,80,76,65,84,70,79,82,77,83,117,16,0,0, + 0,95,109,97,107,101,95,114,101,108,97,120,95,99,97,115, + 101,117,7,0,0,0,95,119,95,108,111,110,103,117,7,0, + 0,0,95,114,95,108,111,110,103,117,10,0,0,0,95,112, + 97,116,104,95,106,111,105,110,117,12,0,0,0,95,112,97, + 116,104,95,101,120,105,115,116,115,117,18,0,0,0,95,112, + 97,116,104,95,105,115,95,109,111,100,101,95,116,121,112,101, + 117,12,0,0,0,95,112,97,116,104,95,105,115,102,105,108, + 101,117,11,0,0,0,95,112,97,116,104,95,105,115,100,105, + 114,117,17,0,0,0,95,112,97,116,104,95,119,105,116,104, + 111,117,116,95,101,120,116,117,14,0,0,0,95,112,97,116, + 104,95,97,98,115,111,108,117,116,101,117,13,0,0,0,95, + 119,114,105,116,101,95,97,116,111,109,105,99,117,5,0,0, + 0,95,119,114,97,112,117,4,0,0,0,116,121,112,101,117, + 8,0,0,0,95,95,99,111,100,101,95,95,117,9,0,0, + 0,99,111,100,101,95,116,121,112,101,117,15,0,0,0,118, + 101,114,98,111,115,101,95,109,101,115,115,97,103,101,117,11, + 0,0,0,115,101,116,95,112,97,99,107,97,103,101,117,10, + 0,0,0,115,101,116,95,108,111,97,100,101,114,117,17,0, + 0,0,109,111,100,117,108,101,95,102,111,114,95,108,111,97, + 100,101,114,117,11,0,0,0,95,99,104,101,99,107,95,110, + 97,109,101,117,17,0,0,0,95,114,101,113,117,105,114,101, + 115,95,98,117,105,108,116,105,110,117,16,0,0,0,95,114, + 101,113,117,105,114,101,115,95,102,114,111,122,101,110,117,12, + 0,0,0,95,115,117,102,102,105,120,95,108,105,115,116,117, + 15,0,0,0,66,117,105,108,116,105,110,73,109,112,111,114, + 116,101,114,117,14,0,0,0,70,114,111,122,101,110,73,109, + 112,111,114,116,101,114,117,13,0,0,0,95,76,111,97,100, + 101,114,66,97,115,105,99,115,117,12,0,0,0,83,111,117, + 114,99,101,76,111,97,100,101,114,117,11,0,0,0,95,70, + 105,108,101,76,111,97,100,101,114,117,17,0,0,0,95,83, + 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,117, + 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, + 105,108,101,76,111,97,100,101,114,117,20,0,0,0,95,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,117,10,0,0,0,80,97,116,104,70,105,110,100,101, + 114,117,11,0,0,0,95,70,105,108,101,70,105,110,100,101, + 114,117,20,0,0,0,95,83,111,117,114,99,101,70,105,110, + 100,101,114,68,101,116,97,105,108,115,117,24,0,0,0,95, + 83,111,117,114,99,101,108,101,115,115,70,105,110,100,101,114, + 68,101,116,97,105,108,115,117,23,0,0,0,95,69,120,116, + 101,110,115,105,111,110,70,105,110,100,101,114,68,101,116,97, + 105,108,115,117,15,0,0,0,95,102,105,108,101,95,112,97, + 116,104,95,104,111,111,107,117,18,0,0,0,95,68,69,70, + 65,85,76,84,95,80,65,84,72,95,72,79,79,75,117,18, + 0,0,0,95,68,101,102,97,117,108,116,80,97,116,104,70, + 105,110,100,101,114,117,18,0,0,0,95,73,109,112,111,114, + 116,76,111,99,107,67,111,110,116,101,120,116,117,13,0,0, + 0,95,114,101,115,111,108,118,101,95,110,97,109,101,117,12, + 0,0,0,95,102,105,110,100,95,109,111,100,117,108,101,117, + 13,0,0,0,95,115,97,110,105,116,121,95,99,104,101,99, + 107,117,19,0,0,0,95,73,77,80,76,73,67,73,84,95, + 77,69,84,65,95,80,65,84,72,117,8,0,0,0,95,69, + 82,82,95,77,83,71,117,14,0,0,0,95,102,105,110,100, + 95,97,110,100,95,108,111,97,100,117,4,0,0,0,78,111, + 110,101,117,11,0,0,0,95,103,99,100,95,105,109,112,111, + 114,116,117,16,0,0,0,95,104,97,110,100,108,101,95,102, + 114,111,109,108,105,115,116,117,17,0,0,0,95,99,97,108, + 99,95,95,95,112,97,99,107,97,103,101,95,95,117,10,0, + 0,0,95,95,105,109,112,111,114,116,95,95,117,6,0,0, + 0,95,115,101,116,117,112,117,8,0,0,0,95,105,110,115, + 116,97,108,108,40,0,0,0,0,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,8,0,0,0,60,109,111,100,117,108, + 101,62,8,0,0,0,115,102,0,0,0,6,14,6,3,12, + 13,12,16,12,15,12,6,12,10,12,10,12,6,12,7,12, + 9,12,13,12,21,12,8,15,4,12,8,12,13,12,11,12, + 32,12,16,12,11,12,11,12,8,19,53,19,47,19,77,22, + 114,19,22,25,38,25,24,19,45,19,68,19,77,19,8,19, + 9,19,11,12,10,6,2,22,21,19,13,12,9,12,15,12, + 17,15,2,6,2,12,41,18,25,12,23,12,15,24,30,12, + 45, }; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 03:58:53 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 03:58:53 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Clarify_that_one_should_not?= =?utf8?q?_use_=5F=5Fimport=5F=5F=28=29_directly=2E_Also_mention?= Message-ID: http://hg.python.org/cpython/rev/0e2274a776c7 changeset: 76313:0e2274a776c7 user: Brett Cannon date: Sat Apr 14 21:58:33 2012 -0400 summary: Clarify that one should not use __import__() directly. Also mention PEP 328 in explaining how 'index' works. files: Doc/library/functions.rst | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1447,8 +1447,9 @@ replaced (by importing the :mod:`builtins` module and assigning to ``builtins.__import__``) in order to change semantics of the :keyword:`import` statement, but nowadays it is usually simpler to use import - hooks (see :pep:`302`). Direct use of :func:`__import__` is rare, except in - cases where you want to import a module whose name is only known at runtime. + hooks (see :pep:`302`) to attain the same goals. Direct use of + :func:`__import__` is entirely discouraged in favor of + :func:`importlib.import_module`. The function imports the module *name*, potentially using the given *globals* and *locals* to determine how to interpret the name in a package context. @@ -1460,7 +1461,8 @@ *level* specifies whether to use absolute or relative imports. ``0`` (the default) means only perform absolute imports. Positive values for *level* indicate the number of parent directories to search relative to the - directory of the module calling :func:`__import__`. + directory of the module calling :func:`__import__` (see :pep:`328` for the + details). When the *name* variable is of the form ``package.module``, normally, the top-level package (the name up till the first dot) is returned, *not* the -- Repository URL: http://hg.python.org/cpython From brett at python.org Sun Apr 15 04:03:43 2012 From: brett at python.org (Brett Cannon) Date: Sat, 14 Apr 2012 22:03:43 -0400 Subject: [Python-checkins] cpython: Handle importing pkg.mod by executing In-Reply-To: References: Message-ID: That commit message should have said "Handle importing pkg.mod -- by executing ``__import__('mod', {'__packaging__': 'pkg'}, level=1)`` -- properly (and thus not segfaulting)." Although honestly I'm not sure if the semantics make sense since this is the equivalent of ``import .mod`` from within pkg and I'm not sure what they should return: pkg or pkg.mod (currently it's the latter)? Not sure I even really care since it's such a messed up way of specifying it and you should be using importlib.import_module() anyway which lacks these issues). On Sat, Apr 14, 2012 at 21:50, brett.cannon wrote: > http://hg.python.org/cpython/rev/9e8cbf07068a > changeset: 76312:9e8cbf07068a > user: Brett Cannon > date: Sat Apr 14 21:50:00 2012 -0400 > summary: > Handle importing pkg.mod by executing > __import__('mod', {'__packaging__': 'pkg', level=1) w/o properly (and > thus not segfaulting). > > files: > Lib/importlib/_bootstrap.py | 2 +- > Lib/importlib/test/import_/test_relative_imports.py | 9 + > Python/import.c | 21 +- > Python/importlib.h | 497 +++++---- > 4 files changed, 276 insertions(+), 253 deletions(-) > > > diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py > --- a/Lib/importlib/_bootstrap.py > +++ b/Lib/importlib/_bootstrap.py > @@ -1083,7 +1083,7 @@ > return module > else: > cut_off = len(name) - len(name.partition('.')[0]) > - return sys.modules[module.__name__[:-cut_off]] > + return > sys.modules[module.__name__[:len(module.__name__)-cut_off]] > else: > return _handle_fromlist(module, fromlist, _gcd_import) > > diff --git a/Lib/importlib/test/import_/test_relative_imports.py > b/Lib/importlib/test/import_/test_relative_imports.py > --- a/Lib/importlib/test/import_/test_relative_imports.py > +++ b/Lib/importlib/test/import_/test_relative_imports.py > @@ -193,6 +193,15 @@ > self.assertEqual(module.__name__, '__runpy_pkg__.uncle.cousin') > self.relative_import_test(create, globals_, callback) > > + def test_import_relative_import_no_fromlist(self): > + # Import a relative module w/ no fromlist. > + create = ['crash.__init__', 'crash.mod'] > + globals_ = [{'__package__': 'crash', '__name__': 'crash'}] > + def callback(global_): > + import_util.import_('crash') > + mod = import_util.import_('mod', global_, {}, [], 1) > + self.assertEqual(mod.__name__, 'crash.mod') > + self.relative_import_test(create, globals_, callback) > > > def test_main(): > diff --git a/Python/import.c b/Python/import.c > --- a/Python/import.c > +++ b/Python/import.c > @@ -3016,20 +3016,33 @@ > Py_DECREF(partition); > > if (level == 0) { > - final_mod = PyDict_GetItemWithError(interp->modules, > front); > + final_mod = PyDict_GetItem(interp->modules, front); > Py_DECREF(front); > - Py_XINCREF(final_mod); > + if (final_mod == NULL) { > + PyErr_Format(PyExc_KeyError, > + "%R not in sys.modules as expected", > front); > + } > + else { > + Py_INCREF(final_mod); > + } > } > else { > Py_ssize_t cut_off = PyUnicode_GetLength(name) - > PyUnicode_GetLength(front); > Py_ssize_t abs_name_len = PyUnicode_GetLength(abs_name); > - PyObject *to_return = PyUnicode_Substring(name, 0, > + PyObject *to_return = PyUnicode_Substring(abs_name, 0, > abs_name_len - > cut_off); > > final_mod = PyDict_GetItem(interp->modules, to_return); > - Py_INCREF(final_mod); > Py_DECREF(to_return); > + if (final_mod == NULL) { > + PyErr_Format(PyExc_KeyError, > + "%R not in sys.modules as expected", > + to_return); > + } > + else { > + Py_INCREF(final_mod); > + } > } > } > else { > diff --git a/Python/importlib.h b/Python/importlib.h > --- a/Python/importlib.h > +++ b/Python/importlib.h > @@ -2826,262 +2826,263 @@ > 0,115,12,0,0,0,0,7,15,1,12,1,10,1,12,1, > 25,1,117,17,0,0,0,95,99,97,108,99,95,95,95,112, > 97,99,107,97,103,101,95,95,99,5,0,0,0,0,0,0, > - 0,8,0,0,0,4,0,0,0,67,0,0,0,115,192,0, > + 0,8,0,0,0,5,0,0,0,67,0,0,0,115,204,0, > 0,0,124,4,0,100,1,0,107,2,0,114,27,0,116,0, > 0,124,0,0,131,1,0,125,5,0,110,30,0,116,1,0, > 124,1,0,131,1,0,125,6,0,116,0,0,124,0,0,124, > - 6,0,124,4,0,131,3,0,125,5,0,124,3,0,115,172, > + 6,0,124,4,0,131,3,0,125,5,0,124,3,0,115,184, > 0,124,4,0,100,1,0,107,2,0,114,99,0,116,2,0, > 106,3,0,124,0,0,106,4,0,100,2,0,131,1,0,100, > 1,0,25,25,83,124,0,0,115,109,0,124,5,0,83,116, > 5,0,124,0,0,131,1,0,116,5,0,124,0,0,106,4, > 0,100,2,0,131,1,0,100,1,0,25,131,1,0,24,125, > 7,0,116,2,0,106,3,0,124,5,0,106,6,0,100,3, > - 0,124,7,0,11,133,2,0,25,25,83,110,16,0,116,7, > - 0,124,5,0,124,3,0,116,0,0,131,3,0,83,100,3, > - 0,83,40,4,0,0,0,117,214,1,0,0,73,109,112,111, > - 114,116,32,97,32,109,111,100,117,108,101,46,10,10,32,32, > - 32,32,84,104,101,32,39,103,108,111,98,97,108,115,39,32, > - 97,114,103,117,109,101,110,116,32,105,115,32,117,115,101,100, > - 32,116,111,32,105,110,102,101,114,32,119,104,101,114,101,32, > - 116,104,101,32,105,109,112,111,114,116,32,105,115,32,111,99, > - 99,117,114,105,110,103,32,102,114,111,109,10,32,32,32,32, > - 116,111,32,104,97,110,100,108,101,32,114,101,108,97,116,105, > - 118,101,32,105,109,112,111,114,116,115,46,32,84,104,101,32, > - 39,108,111,99,97,108,115,39,32,97,114,103,117,109,101,110, > - 116,32,105,115,32,105,103,110,111,114,101,100,46,32,84,104, > - 101,10,32,32,32,32,39,102,114,111,109,108,105,115,116,39, > - 32,97,114,103,117,109,101,110,116,32,115,112,101,99,105,102, > - 105,101,115,32,119,104,97,116,32,115,104,111,117,108,100,32, > - 101,120,105,115,116,32,97,115,32,97,116,116,114,105,98,117, > - 116,101,115,32,111,110,32,116,104,101,32,109,111,100,117,108, > - 101,10,32,32,32,32,98,101,105,110,103,32,105,109,112,111, > - 114,116,101,100,32,40,101,46,103,46,32,96,96,102,114,111, > - 109,32,109,111,100,117,108,101,32,105,109,112,111,114,116,32, > - 60,102,114,111,109,108,105,115,116,62,96,96,41,46,32,32, > - 84,104,101,32,39,108,101,118,101,108,39,10,32,32,32,32, > - 97,114,103,117,109,101,110,116,32,114,101,112,114,101,115,101, > - 110,116,115,32,116,104,101,32,112,97,99,107,97,103,101,32, > - 108,111,99,97,116,105,111,110,32,116,111,32,105,109,112,111, > - 114,116,32,102,114,111,109,32,105,110,32,97,32,114,101,108, > - 97,116,105,118,101,10,32,32,32,32,105,109,112,111,114,116, > - 32,40,101,46,103,46,32,96,96,102,114,111,109,32,46,46, > - 112,107,103,32,105,109,112,111,114,116,32,109,111,100,96,96, > - 32,119,111,117,108,100,32,104,97,118,101,32,97,32,39,108, > - 101,118,101,108,39,32,111,102,32,50,41,46,10,10,32,32, > - 32,32,105,0,0,0,0,117,1,0,0,0,46,78,40,8, > - 0,0,0,117,11,0,0,0,95,103,99,100,95,105,109,112, > - 111,114,116,117,17,0,0,0,95,99,97,108,99,95,95,95, > - 112,97,99,107,97,103,101,95,95,117,3,0,0,0,115,121, > - 115,117,7,0,0,0,109,111,100,117,108,101,115,117,9,0, > - 0,0,112,97,114,116,105,116,105,111,110,117,3,0,0,0, > - 108,101,110,117,8,0,0,0,95,95,110,97,109,101,95,95, > - 117,16,0,0,0,95,104,97,110,100,108,101,95,102,114,111, > - 109,108,105,115,116,40,8,0,0,0,117,4,0,0,0,110, > - 97,109,101,117,7,0,0,0,103,108,111,98,97,108,115,117, > - 6,0,0,0,108,111,99,97,108,115,117,8,0,0,0,102, > - 114,111,109,108,105,115,116,117,5,0,0,0,108,101,118,101, > - 108,117,6,0,0,0,109,111,100,117,108,101,117,7,0,0, > - 0,112,97,99,107,97,103,101,117,7,0,0,0,99,117,116, > - 95,111,102,102,40,0,0,0,0,40,0,0,0,0,117,29, > - 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, > - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, > - 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,37, > - 4,0,0,115,24,0,0,0,0,11,12,1,15,2,12,1, > - 18,1,6,3,12,1,24,1,6,1,4,2,35,1,28,2, > - 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,99, > - 2,0,0,0,0,0,0,0,9,0,0,0,12,0,0,0, > - 67,0,0,0,115,109,1,0,0,124,1,0,97,0,0,124, > - 0,0,97,1,0,120,47,0,116,0,0,116,1,0,102,2, > - 0,68,93,33,0,125,2,0,116,2,0,124,2,0,100,1, > - 0,131,2,0,115,25,0,116,3,0,124,2,0,95,4,0, > - 113,25,0,113,25,0,87,116,1,0,106,5,0,116,6,0, > - 25,125,3,0,120,76,0,100,17,0,68,93,68,0,125,4, > - 0,124,4,0,116,1,0,106,5,0,107,7,0,114,121,0, > - 116,3,0,106,7,0,124,4,0,131,1,0,125,5,0,110, > - 13,0,116,1,0,106,5,0,124,4,0,25,125,5,0,116, > - 8,0,124,3,0,124,4,0,124,5,0,131,3,0,1,113, > - 82,0,87,120,153,0,100,18,0,100,19,0,100,20,0,103, > - 3,0,68,93,124,0,92,2,0,125,6,0,125,7,0,124, > - 6,0,116,1,0,106,5,0,107,6,0,114,214,0,116,1, > - 0,106,5,0,124,6,0,25,125,8,0,80,113,170,0,121, > - 56,0,116,3,0,106,7,0,124,6,0,131,1,0,125,8, > - 0,124,6,0,100,10,0,107,2,0,114,12,1,100,11,0, > - 116,1,0,106,9,0,107,6,0,114,12,1,100,7,0,125, > - 7,0,110,0,0,80,87,113,170,0,4,116,10,0,107,10, > - 0,114,37,1,1,1,1,119,170,0,89,113,170,0,88,113, > - 170,0,87,116,10,0,100,12,0,131,1,0,130,1,0,116, > - 8,0,124,3,0,100,13,0,124,8,0,131,3,0,1,116, > - 8,0,124,3,0,100,14,0,124,7,0,131,3,0,1,116, > - 8,0,124,3,0,100,15,0,116,11,0,131,0,0,131,3, > - 0,1,100,16,0,83,40,21,0,0,0,117,249,0,0,0, > - 83,101,116,117,112,32,105,109,112,111,114,116,108,105,98,32, > - 98,121,32,105,109,112,111,114,116,105,110,103,32,110,101,101, > - 100,101,100,32,98,117,105,108,116,45,105,110,32,109,111,100, > - 117,108,101,115,32,97,110,100,32,105,110,106,101,99,116,105, > - 110,103,32,116,104,101,109,10,32,32,32,32,105,110,116,111, > - 32,116,104,101,32,103,108,111,98,97,108,32,110,97,109,101, > - 115,112,97,99,101,46,10,10,32,32,32,32,65,115,32,115, > - 121,115,32,105,115,32,110,101,101,100,101,100,32,102,111,114, > - 32,115,121,115,46,109,111,100,117,108,101,115,32,97,99,99, > - 101,115,115,32,97,110,100,32,105,109,112,32,105,115,32,110, > - 101,101,100,101,100,32,116,111,32,108,111,97,100,32,98,117, > - 105,108,116,45,105,110,10,32,32,32,32,109,111,100,117,108, > - 101,115,44,32,116,104,111,115,101,32,116,119,111,32,109,111, > - 100,117,108,101,115,32,109,117,115,116,32,98,101,32,101,120, > - 112,108,105,99,105,116,108,121,32,112,97,115,115,101,100,32, > - 105,110,46,10,10,32,32,32,32,117,10,0,0,0,95,95, > - 108,111,97,100,101,114,95,95,117,3,0,0,0,95,105,111, > - 117,9,0,0,0,95,119,97,114,110,105,110,103,115,117,8, > - 0,0,0,98,117,105,108,116,105,110,115,117,7,0,0,0, > - 109,97,114,115,104,97,108,117,5,0,0,0,112,111,115,105, > - 120,117,1,0,0,0,47,117,2,0,0,0,110,116,117,1, > - 0,0,0,92,117,3,0,0,0,111,115,50,117,7,0,0, > - 0,69,77,88,32,71,67,67,117,30,0,0,0,105,109,112, > - 111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,32, > - 112,111,115,105,120,32,111,114,32,110,116,117,3,0,0,0, > - 95,111,115,117,8,0,0,0,112,97,116,104,95,115,101,112, > - 117,11,0,0,0,95,114,101,108,97,120,95,99,97,115,101, > - 78,40,4,0,0,0,117,3,0,0,0,95,105,111,117,9, > - 0,0,0,95,119,97,114,110,105,110,103,115,117,8,0,0, > - 0,98,117,105,108,116,105,110,115,117,7,0,0,0,109,97, > - 114,115,104,97,108,40,2,0,0,0,117,5,0,0,0,112, > - 111,115,105,120,117,1,0,0,0,47,40,2,0,0,0,117, > - 2,0,0,0,110,116,117,1,0,0,0,92,40,2,0,0, > - 0,117,3,0,0,0,111,115,50,117,1,0,0,0,92,40, > - 12,0,0,0,117,3,0,0,0,105,109,112,117,3,0,0, > - 0,115,121,115,117,7,0,0,0,104,97,115,97,116,116,114, > - 117,15,0,0,0,66,117,105,108,116,105,110,73,109,112,111, > - 114,116,101,114,117,10,0,0,0,95,95,108,111,97,100,101, > - 114,95,95,117,7,0,0,0,109,111,100,117,108,101,115,117, > - 8,0,0,0,95,95,110,97,109,101,95,95,117,11,0,0, > - 0,108,111,97,100,95,109,111,100,117,108,101,117,7,0,0, > - 0,115,101,116,97,116,116,114,117,7,0,0,0,118,101,114, > - 115,105,111,110,117,11,0,0,0,73,109,112,111,114,116,69, > - 114,114,111,114,117,16,0,0,0,95,109,97,107,101,95,114, > - 101,108,97,120,95,99,97,115,101,40,9,0,0,0,117,10, > - 0,0,0,115,121,115,95,109,111,100,117,108,101,117,10,0, > - 0,0,105,109,112,95,109,111,100,117,108,101,117,6,0,0, > - 0,109,111,100,117,108,101,117,11,0,0,0,115,101,108,102, > - 95,109,111,100,117,108,101,117,12,0,0,0,98,117,105,108, > - 116,105,110,95,110,97,109,101,117,14,0,0,0,98,117,105, > - 108,116,105,110,95,109,111,100,117,108,101,117,10,0,0,0, > - 98,117,105,108,116,105,110,95,111,115,117,8,0,0,0,112, > - 97,116,104,95,115,101,112,117,9,0,0,0,111,115,95,109, > - 111,100,117,108,101,40,0,0,0,0,40,0,0,0,0,117, > - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, > - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, > - 62,117,6,0,0,0,95,115,101,116,117,112,67,4,0,0, > - 115,52,0,0,0,0,9,6,1,6,2,19,1,15,1,16, > - 2,13,1,13,1,15,1,18,2,13,1,20,2,28,1,15, > - 1,13,1,4,2,3,1,15,2,27,1,9,1,5,1,13, > - 1,12,2,12,1,16,1,16,2,117,6,0,0,0,95,115, > - 101,116,117,112,99,2,0,0,0,0,0,0,0,3,0,0, > - 0,3,0,0,0,67,0,0,0,115,44,0,0,0,116,0, > - 0,124,0,0,124,1,0,131,2,0,1,116,1,0,106,2, > - 0,125,2,0,116,2,0,116,1,0,95,2,0,124,2,0, > - 116,1,0,95,3,0,100,1,0,83,40,2,0,0,0,117, > - 201,0,0,0,73,110,115,116,97,108,108,32,105,109,112,111, > - 114,116,108,105,98,32,97,115,32,116,104,101,32,105,109,112, > - 108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,105, > - 109,112,111,114,116,46,10,10,32,32,32,32,73,116,32,105, > - 115,32,97,115,115,117,109,101,100,32,116,104,97,116,32,105, > - 109,112,32,97,110,100,32,115,121,115,32,104,97,118,101,32, > - 98,101,101,110,32,105,109,112,111,114,116,101,100,32,97,110, > - 100,32,105,110,106,101,99,116,101,100,32,105,110,116,111,32, > - 116,104,101,10,32,32,32,32,103,108,111,98,97,108,32,110, > - 97,109,101,115,112,97,99,101,32,102,111,114,32,116,104,101, > - 32,109,111,100,117,108,101,32,112,114,105,111,114,32,116,111, > - 32,99,97,108,108,105,110,103,32,116,104,105,115,32,102,117, > - 110,99,116,105,111,110,46,10,10,32,32,32,32,78,40,4, > - 0,0,0,117,6,0,0,0,95,115,101,116,117,112,117,8, > - 0,0,0,98,117,105,108,116,105,110,115,117,10,0,0,0, > - 95,95,105,109,112,111,114,116,95,95,117,19,0,0,0,95, > - 95,111,114,105,103,105,110,97,108,95,105,109,112,111,114,116, > - 95,95,40,3,0,0,0,117,10,0,0,0,115,121,115,95, > - 109,111,100,117,108,101,117,10,0,0,0,105,109,112,95,109, > - 111,100,117,108,101,117,11,0,0,0,111,114,105,103,95,105, > - 109,112,111,114,116,40,0,0,0,0,40,0,0,0,0,117, > - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, > - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, > - 62,117,8,0,0,0,95,105,110,115,116,97,108,108,112,4, > - 0,0,115,8,0,0,0,0,7,13,1,9,1,9,1,117, > - 8,0,0,0,95,105,110,115,116,97,108,108,78,40,3,0, > - 0,0,117,3,0,0,0,119,105,110,117,6,0,0,0,99, > - 121,103,119,105,110,117,6,0,0,0,100,97,114,119,105,110, > - 40,55,0,0,0,117,7,0,0,0,95,95,100,111,99,95, > - 95,117,26,0,0,0,67,65,83,69,95,73,78,83,69,78, > - 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, > + 0,116,5,0,124,5,0,106,6,0,131,1,0,124,7,0, > + 24,133,2,0,25,25,83,110,16,0,116,7,0,124,5,0, > + 124,3,0,116,0,0,131,3,0,83,100,3,0,83,40,4, > + 0,0,0,117,214,1,0,0,73,109,112,111,114,116,32,97, > + 32,109,111,100,117,108,101,46,10,10,32,32,32,32,84,104, > + 101,32,39,103,108,111,98,97,108,115,39,32,97,114,103,117, > + 109,101,110,116,32,105,115,32,117,115,101,100,32,116,111,32, > + 105,110,102,101,114,32,119,104,101,114,101,32,116,104,101,32, > + 105,109,112,111,114,116,32,105,115,32,111,99,99,117,114,105, > + 110,103,32,102,114,111,109,10,32,32,32,32,116,111,32,104, > + 97,110,100,108,101,32,114,101,108,97,116,105,118,101,32,105, > + 109,112,111,114,116,115,46,32,84,104,101,32,39,108,111,99, > + 97,108,115,39,32,97,114,103,117,109,101,110,116,32,105,115, > + 32,105,103,110,111,114,101,100,46,32,84,104,101,10,32,32, > + 32,32,39,102,114,111,109,108,105,115,116,39,32,97,114,103, > + 117,109,101,110,116,32,115,112,101,99,105,102,105,101,115,32, > + 119,104,97,116,32,115,104,111,117,108,100,32,101,120,105,115, > + 116,32,97,115,32,97,116,116,114,105,98,117,116,101,115,32, > + 111,110,32,116,104,101,32,109,111,100,117,108,101,10,32,32, > + 32,32,98,101,105,110,103,32,105,109,112,111,114,116,101,100, > + 32,40,101,46,103,46,32,96,96,102,114,111,109,32,109,111, > + 100,117,108,101,32,105,109,112,111,114,116,32,60,102,114,111, > + 109,108,105,115,116,62,96,96,41,46,32,32,84,104,101,32, > + 39,108,101,118,101,108,39,10,32,32,32,32,97,114,103,117, > + 109,101,110,116,32,114,101,112,114,101,115,101,110,116,115,32, > + 116,104,101,32,112,97,99,107,97,103,101,32,108,111,99,97, > + 116,105,111,110,32,116,111,32,105,109,112,111,114,116,32,102, > + 114,111,109,32,105,110,32,97,32,114,101,108,97,116,105,118, > + 101,10,32,32,32,32,105,109,112,111,114,116,32,40,101,46, > + 103,46,32,96,96,102,114,111,109,32,46,46,112,107,103,32, > + 105,109,112,111,114,116,32,109,111,100,96,96,32,119,111,117, > + 108,100,32,104,97,118,101,32,97,32,39,108,101,118,101,108, > + 39,32,111,102,32,50,41,46,10,10,32,32,32,32,105,0, > + 0,0,0,117,1,0,0,0,46,78,40,8,0,0,0,117, > + 11,0,0,0,95,103,99,100,95,105,109,112,111,114,116,117, > + 17,0,0,0,95,99,97,108,99,95,95,95,112,97,99,107, > + 97,103,101,95,95,117,3,0,0,0,115,121,115,117,7,0, > + 0,0,109,111,100,117,108,101,115,117,9,0,0,0,112,97, > + 114,116,105,116,105,111,110,117,3,0,0,0,108,101,110,117, > + 8,0,0,0,95,95,110,97,109,101,95,95,117,16,0,0, > + 0,95,104,97,110,100,108,101,95,102,114,111,109,108,105,115, > + 116,40,8,0,0,0,117,4,0,0,0,110,97,109,101,117, > + 7,0,0,0,103,108,111,98,97,108,115,117,6,0,0,0, > + 108,111,99,97,108,115,117,8,0,0,0,102,114,111,109,108, > + 105,115,116,117,5,0,0,0,108,101,118,101,108,117,6,0, > + 0,0,109,111,100,117,108,101,117,7,0,0,0,112,97,99, > + 107,97,103,101,117,7,0,0,0,99,117,116,95,111,102,102, > + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, > + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, > + 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, > + 0,95,95,105,109,112,111,114,116,95,95,37,4,0,0,115, > + 24,0,0,0,0,11,12,1,15,2,12,1,18,1,6,3, > + 12,1,24,1,6,1,4,2,35,1,40,2,117,10,0,0, > + 0,95,95,105,109,112,111,114,116,95,95,99,2,0,0,0, > + 0,0,0,0,9,0,0,0,12,0,0,0,67,0,0,0, > + 115,109,1,0,0,124,1,0,97,0,0,124,0,0,97,1, > + 0,120,47,0,116,0,0,116,1,0,102,2,0,68,93,33, > + 0,125,2,0,116,2,0,124,2,0,100,1,0,131,2,0, > + 115,25,0,116,3,0,124,2,0,95,4,0,113,25,0,113, > + 25,0,87,116,1,0,106,5,0,116,6,0,25,125,3,0, > + 120,76,0,100,17,0,68,93,68,0,125,4,0,124,4,0, > + 116,1,0,106,5,0,107,7,0,114,121,0,116,3,0,106, > + 7,0,124,4,0,131,1,0,125,5,0,110,13,0,116,1, > + 0,106,5,0,124,4,0,25,125,5,0,116,8,0,124,3, > + 0,124,4,0,124,5,0,131,3,0,1,113,82,0,87,120, > + 153,0,100,18,0,100,19,0,100,20,0,103,3,0,68,93, > + 124,0,92,2,0,125,6,0,125,7,0,124,6,0,116,1, > + 0,106,5,0,107,6,0,114,214,0,116,1,0,106,5,0, > + 124,6,0,25,125,8,0,80,113,170,0,121,56,0,116,3, > + 0,106,7,0,124,6,0,131,1,0,125,8,0,124,6,0, > + 100,10,0,107,2,0,114,12,1,100,11,0,116,1,0,106, > + 9,0,107,6,0,114,12,1,100,7,0,125,7,0,110,0, > + 0,80,87,113,170,0,4,116,10,0,107,10,0,114,37,1, > + 1,1,1,119,170,0,89,113,170,0,88,113,170,0,87,116, > + 10,0,100,12,0,131,1,0,130,1,0,116,8,0,124,3, > + 0,100,13,0,124,8,0,131,3,0,1,116,8,0,124,3, > + 0,100,14,0,124,7,0,131,3,0,1,116,8,0,124,3, > + 0,100,15,0,116,11,0,131,0,0,131,3,0,1,100,16, > + 0,83,40,21,0,0,0,117,249,0,0,0,83,101,116,117, > + 112,32,105,109,112,111,114,116,108,105,98,32,98,121,32,105, > + 109,112,111,114,116,105,110,103,32,110,101,101,100,101,100,32, > + 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,115, > + 32,97,110,100,32,105,110,106,101,99,116,105,110,103,32,116, > + 104,101,109,10,32,32,32,32,105,110,116,111,32,116,104,101, > + 32,103,108,111,98,97,108,32,110,97,109,101,115,112,97,99, > + 101,46,10,10,32,32,32,32,65,115,32,115,121,115,32,105, > + 115,32,110,101,101,100,101,100,32,102,111,114,32,115,121,115, > + 46,109,111,100,117,108,101,115,32,97,99,99,101,115,115,32, > + 97,110,100,32,105,109,112,32,105,115,32,110,101,101,100,101, > + 100,32,116,111,32,108,111,97,100,32,98,117,105,108,116,45, > + 105,110,10,32,32,32,32,109,111,100,117,108,101,115,44,32, > + 116,104,111,115,101,32,116,119,111,32,109,111,100,117,108,101, > + 115,32,109,117,115,116,32,98,101,32,101,120,112,108,105,99, > + 105,116,108,121,32,112,97,115,115,101,100,32,105,110,46,10, > + 10,32,32,32,32,117,10,0,0,0,95,95,108,111,97,100, > + 101,114,95,95,117,3,0,0,0,95,105,111,117,9,0,0, > + 0,95,119,97,114,110,105,110,103,115,117,8,0,0,0,98, > + 117,105,108,116,105,110,115,117,7,0,0,0,109,97,114,115, > + 104,97,108,117,5,0,0,0,112,111,115,105,120,117,1,0, > + 0,0,47,117,2,0,0,0,110,116,117,1,0,0,0,92, > + 117,3,0,0,0,111,115,50,117,7,0,0,0,69,77,88, > + 32,71,67,67,117,30,0,0,0,105,109,112,111,114,116,108, > + 105,98,32,114,101,113,117,105,114,101,115,32,112,111,115,105, > + 120,32,111,114,32,110,116,117,3,0,0,0,95,111,115,117, > + 8,0,0,0,112,97,116,104,95,115,101,112,117,11,0,0, > + 0,95,114,101,108,97,120,95,99,97,115,101,78,40,4,0, > + 0,0,117,3,0,0,0,95,105,111,117,9,0,0,0,95, > + 119,97,114,110,105,110,103,115,117,8,0,0,0,98,117,105, > + 108,116,105,110,115,117,7,0,0,0,109,97,114,115,104,97, > + 108,40,2,0,0,0,117,5,0,0,0,112,111,115,105,120, > + 117,1,0,0,0,47,40,2,0,0,0,117,2,0,0,0, > + 110,116,117,1,0,0,0,92,40,2,0,0,0,117,3,0, > + 0,0,111,115,50,117,1,0,0,0,92,40,12,0,0,0, > + 117,3,0,0,0,105,109,112,117,3,0,0,0,115,121,115, > + 117,7,0,0,0,104,97,115,97,116,116,114,117,15,0,0, > + 0,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, > + 117,10,0,0,0,95,95,108,111,97,100,101,114,95,95,117, > + 7,0,0,0,109,111,100,117,108,101,115,117,8,0,0,0, > + 95,95,110,97,109,101,95,95,117,11,0,0,0,108,111,97, > + 100,95,109,111,100,117,108,101,117,7,0,0,0,115,101,116, > + 97,116,116,114,117,7,0,0,0,118,101,114,115,105,111,110, > + 117,11,0,0,0,73,109,112,111,114,116,69,114,114,111,114, > 117,16,0,0,0,95,109,97,107,101,95,114,101,108,97,120, > - 95,99,97,115,101,117,7,0,0,0,95,119,95,108,111,110, > - 103,117,7,0,0,0,95,114,95,108,111,110,103,117,10,0, > - 0,0,95,112,97,116,104,95,106,111,105,110,117,12,0,0, > - 0,95,112,97,116,104,95,101,120,105,115,116,115,117,18,0, > - 0,0,95,112,97,116,104,95,105,115,95,109,111,100,101,95, > - 116,121,112,101,117,12,0,0,0,95,112,97,116,104,95,105, > - 115,102,105,108,101,117,11,0,0,0,95,112,97,116,104,95, > - 105,115,100,105,114,117,17,0,0,0,95,112,97,116,104,95, > - 119,105,116,104,111,117,116,95,101,120,116,117,14,0,0,0, > - 95,112,97,116,104,95,97,98,115,111,108,117,116,101,117,13, > - 0,0,0,95,119,114,105,116,101,95,97,116,111,109,105,99, > - 117,5,0,0,0,95,119,114,97,112,117,4,0,0,0,116, > - 121,112,101,117,8,0,0,0,95,95,99,111,100,101,95,95, > - 117,9,0,0,0,99,111,100,101,95,116,121,112,101,117,15, > - 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, > - 103,101,117,11,0,0,0,115,101,116,95,112,97,99,107,97, > - 103,101,117,10,0,0,0,115,101,116,95,108,111,97,100,101, > - 114,117,17,0,0,0,109,111,100,117,108,101,95,102,111,114, > - 95,108,111,97,100,101,114,117,11,0,0,0,95,99,104,101, > - 99,107,95,110,97,109,101,117,17,0,0,0,95,114,101,113, > - 117,105,114,101,115,95,98,117,105,108,116,105,110,117,16,0, > - 0,0,95,114,101,113,117,105,114,101,115,95,102,114,111,122, > - 101,110,117,12,0,0,0,95,115,117,102,102,105,120,95,108, > - 105,115,116,117,15,0,0,0,66,117,105,108,116,105,110,73, > - 109,112,111,114,116,101,114,117,14,0,0,0,70,114,111,122, > - 101,110,73,109,112,111,114,116,101,114,117,13,0,0,0,95, > - 76,111,97,100,101,114,66,97,115,105,99,115,117,12,0,0, > - 0,83,111,117,114,99,101,76,111,97,100,101,114,117,11,0, > - 0,0,95,70,105,108,101,76,111,97,100,101,114,117,17,0, > - 0,0,95,83,111,117,114,99,101,70,105,108,101,76,111,97, > - 100,101,114,117,21,0,0,0,95,83,111,117,114,99,101,108, > - 101,115,115,70,105,108,101,76,111,97,100,101,114,117,20,0, > - 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, > - 76,111,97,100,101,114,117,10,0,0,0,80,97,116,104,70, > - 105,110,100,101,114,117,11,0,0,0,95,70,105,108,101,70, > - 105,110,100,101,114,117,20,0,0,0,95,83,111,117,114,99, > - 101,70,105,110,100,101,114,68,101,116,97,105,108,115,117,24, > - 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, > - 110,100,101,114,68,101,116,97,105,108,115,117,23,0,0,0, > - 95,69,120,116,101,110,115,105,111,110,70,105,110,100,101,114, > - 68,101,116,97,105,108,115,117,15,0,0,0,95,102,105,108, > - 101,95,112,97,116,104,95,104,111,111,107,117,18,0,0,0, > - 95,68,69,70,65,85,76,84,95,80,65,84,72,95,72,79, > - 79,75,117,18,0,0,0,95,68,101,102,97,117,108,116,80, > - 97,116,104,70,105,110,100,101,114,117,18,0,0,0,95,73, > - 109,112,111,114,116,76,111,99,107,67,111,110,116,101,120,116, > - 117,13,0,0,0,95,114,101,115,111,108,118,101,95,110,97, > - 109,101,117,12,0,0,0,95,102,105,110,100,95,109,111,100, > - 117,108,101,117,13,0,0,0,95,115,97,110,105,116,121,95, > - 99,104,101,99,107,117,19,0,0,0,95,73,77,80,76,73, > - 67,73,84,95,77,69,84,65,95,80,65,84,72,117,8,0, > - 0,0,95,69,82,82,95,77,83,71,117,14,0,0,0,95, > - 102,105,110,100,95,97,110,100,95,108,111,97,100,117,4,0, > - 0,0,78,111,110,101,117,11,0,0,0,95,103,99,100,95, > - 105,109,112,111,114,116,117,16,0,0,0,95,104,97,110,100, > - 108,101,95,102,114,111,109,108,105,115,116,117,17,0,0,0, > - 95,99,97,108,99,95,95,95,112,97,99,107,97,103,101,95, > - 95,117,10,0,0,0,95,95,105,109,112,111,114,116,95,95, > - 117,6,0,0,0,95,115,101,116,117,112,117,8,0,0,0, > - 95,105,110,115,116,97,108,108,40,0,0,0,0,40,0,0, > - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, > - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, > - 111,111,116,115,116,114,97,112,62,117,8,0,0,0,60,109, > - 111,100,117,108,101,62,8,0,0,0,115,102,0,0,0,6, > - 14,6,3,12,13,12,16,12,15,12,6,12,10,12,10,12, > - 6,12,7,12,9,12,13,12,21,12,8,15,4,12,8,12, > - 13,12,11,12,32,12,16,12,11,12,11,12,8,19,53,19, > - 47,19,77,22,114,19,22,25,38,25,24,19,45,19,68,19, > - 77,19,8,19,9,19,11,12,10,6,2,22,21,19,13,12, > - 9,12,15,12,17,15,2,6,2,12,41,18,25,12,23,12, > - 15,24,30,12,45, > + 95,99,97,115,101,40,9,0,0,0,117,10,0,0,0,115, > + 121,115,95,109,111,100,117,108,101,117,10,0,0,0,105,109, > + 112,95,109,111,100,117,108,101,117,6,0,0,0,109,111,100, > + 117,108,101,117,11,0,0,0,115,101,108,102,95,109,111,100, > + 117,108,101,117,12,0,0,0,98,117,105,108,116,105,110,95, > + 110,97,109,101,117,14,0,0,0,98,117,105,108,116,105,110, > + 95,109,111,100,117,108,101,117,10,0,0,0,98,117,105,108, > + 116,105,110,95,111,115,117,8,0,0,0,112,97,116,104,95, > + 115,101,112,117,9,0,0,0,111,115,95,109,111,100,117,108, > + 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, > + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, > + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,6,0, > + 0,0,95,115,101,116,117,112,67,4,0,0,115,52,0,0, > + 0,0,9,6,1,6,2,19,1,15,1,16,2,13,1,13, > + 1,15,1,18,2,13,1,20,2,28,1,15,1,13,1,4, > + 2,3,1,15,2,27,1,9,1,5,1,13,1,12,2,12, > + 1,16,1,16,2,117,6,0,0,0,95,115,101,116,117,112, > + 99,2,0,0,0,0,0,0,0,3,0,0,0,3,0,0, > + 0,67,0,0,0,115,44,0,0,0,116,0,0,124,0,0, > + 124,1,0,131,2,0,1,116,1,0,106,2,0,125,2,0, > + 116,2,0,116,1,0,95,2,0,124,2,0,116,1,0,95, > + 3,0,100,1,0,83,40,2,0,0,0,117,201,0,0,0, > + 73,110,115,116,97,108,108,32,105,109,112,111,114,116,108,105, > + 98,32,97,115,32,116,104,101,32,105,109,112,108,101,109,101, > + 110,116,97,116,105,111,110,32,111,102,32,105,109,112,111,114, > + 116,46,10,10,32,32,32,32,73,116,32,105,115,32,97,115, > + 115,117,109,101,100,32,116,104,97,116,32,105,109,112,32,97, > + 110,100,32,115,121,115,32,104,97,118,101,32,98,101,101,110, > + 32,105,109,112,111,114,116,101,100,32,97,110,100,32,105,110, > + 106,101,99,116,101,100,32,105,110,116,111,32,116,104,101,10, > + 32,32,32,32,103,108,111,98,97,108,32,110,97,109,101,115, > + 112,97,99,101,32,102,111,114,32,116,104,101,32,109,111,100, > + 117,108,101,32,112,114,105,111,114,32,116,111,32,99,97,108, > + 108,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105, > + 111,110,46,10,10,32,32,32,32,78,40,4,0,0,0,117, > + 6,0,0,0,95,115,101,116,117,112,117,8,0,0,0,98, > + 117,105,108,116,105,110,115,117,10,0,0,0,95,95,105,109, > + 112,111,114,116,95,95,117,19,0,0,0,95,95,111,114,105, > + 103,105,110,97,108,95,105,109,112,111,114,116,95,95,40,3, > + 0,0,0,117,10,0,0,0,115,121,115,95,109,111,100,117, > + 108,101,117,10,0,0,0,105,109,112,95,109,111,100,117,108, > + 101,117,11,0,0,0,111,114,105,103,95,105,109,112,111,114, > + 116,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, > + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, > + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, > + 0,0,95,105,110,115,116,97,108,108,112,4,0,0,115,8, > + 0,0,0,0,7,13,1,9,1,9,1,117,8,0,0,0, > + 95,105,110,115,116,97,108,108,78,40,3,0,0,0,117,3, > + 0,0,0,119,105,110,117,6,0,0,0,99,121,103,119,105, > + 110,117,6,0,0,0,100,97,114,119,105,110,40,55,0,0, > + 0,117,7,0,0,0,95,95,100,111,99,95,95,117,26,0, > + 0,0,67,65,83,69,95,73,78,83,69,78,83,73,84,73, > + 86,69,95,80,76,65,84,70,79,82,77,83,117,16,0,0, > + 0,95,109,97,107,101,95,114,101,108,97,120,95,99,97,115, > + 101,117,7,0,0,0,95,119,95,108,111,110,103,117,7,0, > + 0,0,95,114,95,108,111,110,103,117,10,0,0,0,95,112, > + 97,116,104,95,106,111,105,110,117,12,0,0,0,95,112,97, > + 116,104,95,101,120,105,115,116,115,117,18,0,0,0,95,112, > + 97,116,104,95,105,115,95,109,111,100,101,95,116,121,112,101, > + 117,12,0,0,0,95,112,97,116,104,95,105,115,102,105,108, > + 101,117,11,0,0,0,95,112,97,116,104,95,105,115,100,105, > + 114,117,17,0,0,0,95,112,97,116,104,95,119,105,116,104, > + 111,117,116,95,101,120,116,117,14,0,0,0,95,112,97,116, > + 104,95,97,98,115,111,108,117,116,101,117,13,0,0,0,95, > + 119,114,105,116,101,95,97,116,111,109,105,99,117,5,0,0, > + 0,95,119,114,97,112,117,4,0,0,0,116,121,112,101,117, > + 8,0,0,0,95,95,99,111,100,101,95,95,117,9,0,0, > + 0,99,111,100,101,95,116,121,112,101,117,15,0,0,0,118, > + 101,114,98,111,115,101,95,109,101,115,115,97,103,101,117,11, > + 0,0,0,115,101,116,95,112,97,99,107,97,103,101,117,10, > + 0,0,0,115,101,116,95,108,111,97,100,101,114,117,17,0, > + 0,0,109,111,100,117,108,101,95,102,111,114,95,108,111,97, > + 100,101,114,117,11,0,0,0,95,99,104,101,99,107,95,110, > + 97,109,101,117,17,0,0,0,95,114,101,113,117,105,114,101, > + 115,95,98,117,105,108,116,105,110,117,16,0,0,0,95,114, > + 101,113,117,105,114,101,115,95,102,114,111,122,101,110,117,12, > + 0,0,0,95,115,117,102,102,105,120,95,108,105,115,116,117, > + 15,0,0,0,66,117,105,108,116,105,110,73,109,112,111,114, > + 116,101,114,117,14,0,0,0,70,114,111,122,101,110,73,109, > + 112,111,114,116,101,114,117,13,0,0,0,95,76,111,97,100, > + 101,114,66,97,115,105,99,115,117,12,0,0,0,83,111,117, > + 114,99,101,76,111,97,100,101,114,117,11,0,0,0,95,70, > + 105,108,101,76,111,97,100,101,114,117,17,0,0,0,95,83, > + 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,117, > + 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, > + 105,108,101,76,111,97,100,101,114,117,20,0,0,0,95,69, > + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, > + 101,114,117,10,0,0,0,80,97,116,104,70,105,110,100,101, > + 114,117,11,0,0,0,95,70,105,108,101,70,105,110,100,101, > + 114,117,20,0,0,0,95,83,111,117,114,99,101,70,105,110, > + 100,101,114,68,101,116,97,105,108,115,117,24,0,0,0,95, > + 83,111,117,114,99,101,108,101,115,115,70,105,110,100,101,114, > + 68,101,116,97,105,108,115,117,23,0,0,0,95,69,120,116, > + 101,110,115,105,111,110,70,105,110,100,101,114,68,101,116,97, > + 105,108,115,117,15,0,0,0,95,102,105,108,101,95,112,97, > + 116,104,95,104,111,111,107,117,18,0,0,0,95,68,69,70, > + 65,85,76,84,95,80,65,84,72,95,72,79,79,75,117,18, > + 0,0,0,95,68,101,102,97,117,108,116,80,97,116,104,70, > + 105,110,100,101,114,117,18,0,0,0,95,73,109,112,111,114, > + 116,76,111,99,107,67,111,110,116,101,120,116,117,13,0,0, > + 0,95,114,101,115,111,108,118,101,95,110,97,109,101,117,12, > + 0,0,0,95,102,105,110,100,95,109,111,100,117,108,101,117, > + 13,0,0,0,95,115,97,110,105,116,121,95,99,104,101,99, > + 107,117,19,0,0,0,95,73,77,80,76,73,67,73,84,95, > + 77,69,84,65,95,80,65,84,72,117,8,0,0,0,95,69, > + 82,82,95,77,83,71,117,14,0,0,0,95,102,105,110,100, > + 95,97,110,100,95,108,111,97,100,117,4,0,0,0,78,111, > + 110,101,117,11,0,0,0,95,103,99,100,95,105,109,112,111, > + 114,116,117,16,0,0,0,95,104,97,110,100,108,101,95,102, > + 114,111,109,108,105,115,116,117,17,0,0,0,95,99,97,108, > + 99,95,95,95,112,97,99,107,97,103,101,95,95,117,10,0, > + 0,0,95,95,105,109,112,111,114,116,95,95,117,6,0,0, > + 0,95,115,101,116,117,112,117,8,0,0,0,95,105,110,115, > + 116,97,108,108,40,0,0,0,0,40,0,0,0,0,40,0, > + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, > + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, > + 116,114,97,112,62,117,8,0,0,0,60,109,111,100,117,108, > + 101,62,8,0,0,0,115,102,0,0,0,6,14,6,3,12, > + 13,12,16,12,15,12,6,12,10,12,10,12,6,12,7,12, > + 9,12,13,12,21,12,8,15,4,12,8,12,13,12,11,12, > + 32,12,16,12,11,12,11,12,8,19,53,19,47,19,77,22, > + 114,19,22,25,38,25,24,19,45,19,68,19,77,19,8,19, > + 9,19,11,12,10,6,2,22,21,19,13,12,9,12,15,12, > + 17,15,2,6,2,12,41,18,25,12,23,12,15,24,30,12, > + 45, > }; > > -- > Repository URL: http://hg.python.org/cpython > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From solipsis at pitrou.net Sun Apr 15 05:43:12 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 15 Apr 2012 05:43:12 +0200 Subject: [Python-checkins] Daily reference leaks (556b9bafdee8): sum=1144 Message-ID: results for 556b9bafdee8 on branch "default" -------------------------------------------- test_support leaked [-2, 2, 0] references, sum=0 test_bz2 leaked [-1, -1, -1] references, sum=-3 test_capi leaked [78, 78, 78] references, sum=234 test_concurrent_futures leaked [120, 120, 120] references, sum=360 test_hashlib leaked [-1, -1, -1] references, sum=-3 test_import leaked [4, 4, 4] references, sum=12 test_lib2to3 leaked [14, 14, 14] references, sum=42 test_multiprocessing leaked [149, 149, 150] references, sum=448 test_runpy leaked [18, 18, 18] references, sum=54 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogBFPz19', '-x'] From python-checkins at python.org Sun Apr 15 07:35:20 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 07:35:20 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Plug_a_refleak=2E?= Message-ID: http://hg.python.org/cpython/rev/c7bf93802f5d changeset: 76314:c7bf93802f5d user: Brett Cannon date: Sun Apr 15 01:35:05 2012 -0400 summary: Plug a refleak. files: Python/pythonrun.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -199,8 +199,6 @@ PyObject *value; /* Import _importlib through its frozen version, _frozen_importlib. */ - /* XXX(bcannon): The file path for _frozen_importlib is completely off - */ if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) { Py_FatalError("Py_Initialize: can't import _frozen_importlib"); } @@ -237,6 +235,7 @@ Py_FatalError("Py_Initialize: importlib install failed"); } Py_DECREF(value); + Py_DECREF(impmod); _PyImportZip_Init(); } -- Repository URL: http://hg.python.org/cpython From brett at python.org Sun Apr 15 07:51:39 2012 From: brett at python.org (Brett Cannon) Date: Sun, 15 Apr 2012 01:51:39 -0400 Subject: [Python-checkins] Daily reference leaks (556b9bafdee8): sum=1144 In-Reply-To: References: Message-ID: I'm going to guess my bootstrap patch caused most of these. =) test_capi is now plugged, so I'm going to assume Python/pythonrun.c:import_init() is taken care of. The real question is where in http://hg.python.org/cpython/rev/2dd046be2c88 are the other leaks coming from. Any help would be great as I have been staring at this code for so long I really don't want to have to go hunting for refleaks right now. On Sat, Apr 14, 2012 at 23:43, wrote: > results for 556b9bafdee8 on branch "default" > -------------------------------------------- > > test_support leaked [-2, 2, 0] references, sum=0 > test_bz2 leaked [-1, -1, -1] references, sum=-3 > test_capi leaked [78, 78, 78] references, sum=234 > test_concurrent_futures leaked [120, 120, 120] references, sum=360 > test_hashlib leaked [-1, -1, -1] references, sum=-3 > test_import leaked [4, 4, 4] references, sum=12 > test_lib2to3 leaked [14, 14, 14] references, sum=42 > test_multiprocessing leaked [149, 149, 150] references, sum=448 > test_runpy leaked [18, 18, 18] references, sum=54 > > > Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', > '3:3:/home/antoine/cpython/refleaks/reflogBFPz19', '-x'] > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Sun Apr 15 08:29:16 2012 From: python-checkins at python.org (ross.lagerwall) Date: Sun, 15 Apr 2012 08:29:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Be_less_verbose_when_buildi?= =?utf8?q?ng_dbm=2E?= Message-ID: http://hg.python.org/cpython/rev/7fce7409b347 changeset: 76315:7fce7409b347 parent: 76313:0e2274a776c7 user: Ross Lagerwall date: Sun Apr 15 08:19:35 2012 +0200 summary: Be less verbose when building dbm. files: setup.py | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1072,6 +1072,7 @@ else: missing.append('_sqlite3') + dbm_setup_debug = False # verbose debug prints from this script? dbm_order = ['gdbm'] # The standard Unix dbm module: if platform not in ['cygwin']: @@ -1093,7 +1094,7 @@ ndbm_libs = ['ndbm'] else: ndbm_libs = [] - print("building dbm using ndbm") + if dbm_setup_debug: print("building dbm using ndbm") dbmext = Extension('_dbm', ['_dbmmodule.c'], define_macros=[ ('HAVE_NDBM_H',None), @@ -1108,7 +1109,7 @@ 'gdbm_compat'): gdbm_libs.append('gdbm_compat') if find_file("gdbm/ndbm.h", inc_dirs, []) is not None: - print("building dbm using gdbm") + if dbm_setup_debug: print("building dbm using gdbm") dbmext = Extension( '_dbm', ['_dbmmodule.c'], define_macros=[ @@ -1117,7 +1118,7 @@ libraries = gdbm_libs) break if find_file("gdbm-ndbm.h", inc_dirs, []) is not None: - print("building dbm using gdbm") + if dbm_setup_debug: print("building dbm using gdbm") dbmext = Extension( '_dbm', ['_dbmmodule.c'], define_macros=[ @@ -1127,7 +1128,7 @@ break elif cand == "bdb": if db_incs is not None: - print("building dbm using bdb") + if dbm_setup_debug: print("building dbm using bdb") dbmext = Extension('_dbm', ['_dbmmodule.c'], library_dirs=dblib_dir, runtime_library_dirs=dblib_dir, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 08:29:47 2012 From: python-checkins at python.org (ross.lagerwall) Date: Sun, 15 Apr 2012 08:29:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_Merge_with_remote=2E?= Message-ID: http://hg.python.org/cpython/rev/72902ab938e0 changeset: 76316:72902ab938e0 parent: 76314:c7bf93802f5d parent: 76315:7fce7409b347 user: Ross Lagerwall date: Sun Apr 15 08:23:09 2012 +0200 summary: Merge with remote. files: setup.py | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1072,6 +1072,7 @@ else: missing.append('_sqlite3') + dbm_setup_debug = False # verbose debug prints from this script? dbm_order = ['gdbm'] # The standard Unix dbm module: if platform not in ['cygwin']: @@ -1093,7 +1094,7 @@ ndbm_libs = ['ndbm'] else: ndbm_libs = [] - print("building dbm using ndbm") + if dbm_setup_debug: print("building dbm using ndbm") dbmext = Extension('_dbm', ['_dbmmodule.c'], define_macros=[ ('HAVE_NDBM_H',None), @@ -1108,7 +1109,7 @@ 'gdbm_compat'): gdbm_libs.append('gdbm_compat') if find_file("gdbm/ndbm.h", inc_dirs, []) is not None: - print("building dbm using gdbm") + if dbm_setup_debug: print("building dbm using gdbm") dbmext = Extension( '_dbm', ['_dbmmodule.c'], define_macros=[ @@ -1117,7 +1118,7 @@ libraries = gdbm_libs) break if find_file("gdbm-ndbm.h", inc_dirs, []) is not None: - print("building dbm using gdbm") + if dbm_setup_debug: print("building dbm using gdbm") dbmext = Extension( '_dbm', ['_dbmmodule.c'], define_macros=[ @@ -1127,7 +1128,7 @@ break elif cand == "bdb": if db_incs is not None: - print("building dbm using bdb") + if dbm_setup_debug: print("building dbm using bdb") dbmext = Extension('_dbm', ['_dbmmodule.c'], library_dirs=dblib_dir, runtime_library_dirs=dblib_dir, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 11:46:28 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 15 Apr 2012 11:46:28 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Cameron_Simpson_rew?= =?utf8?q?rote_the_text_of_his_alternative?= Message-ID: http://hg.python.org/peps/rev/b792150ba6b2 changeset: 4250:b792150ba6b2 user: Victor Stinner date: Sun Apr 15 11:46:01 2012 +0200 summary: PEP 418: Cameron Simpson rewrote the text of his alternative files: pep-0418.txt | 57 +++- pep-0418/clockutils.py | 408 +++++++++++++++++++++++++++++ 2 files changed, 457 insertions(+), 8 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -2,7 +2,7 @@ Title: Add monotonic time, performance counter and process time functions Version: $Revision$ Last-Modified: $Date$ -Author: Jim Jewett , Victor Stinner +Author: Cameron Simpson , Jim Jewett , Victor Stinner Status: Draft Type: Standards Track Content-Type: text/x-rst @@ -432,20 +432,45 @@ else? -One function choosing the clock from a list of constraints ----------------------------------------------------------- +Choosing the clock from a list of constraints +--------------------------------------------- -``time.get_clock(*flags)`` with the following flags: +The PEP as proposed offers a few new clocks, but their guarentees +are deliberately loose in order to offer useful clocks on different +platforms. This inherently embeds policy in the calls, and the +caller must thus choose a policy. + +The "choose a clock" approach suggests an additional API to let +callers implement their own policy if necessary +by making most platform clocks available and letting the caller pick amongst them. +The PEP's suggested clocks are still expected to be available for the common +simple use cases. + +To do this two facilities are needed: +an enumeration of clocks, and metadata on the clocks to enable the user to +evaluate their suitability. + +The primary interface is a function make simple choices easy: +the caller can use ``time.get_clock(*flags)`` with some combination of flags. +This include at least: * time.MONOTONIC: clock cannot go backward -* time.STEADY: clock rate is steady and the clock is not adjusted +* time.STEADY: clock rate is steady +* time.ADJUSTED: clock may be adjusted, for example by NTP * time.HIGHRES: clock with the highest precision -time.get_clock() returns None if the clock is found and so calls can -be chained using the or operator. Example:: +It returns a clock object with a .now() method returning the current time. +The clock object is annotated with metadata describing the clock feature set; +its .flags field will contain at least all the requested flags. - get_time = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time() - t = get_time() +time.get_clock() returns None if no matching clock is found and so calls can +be chained using the or operator. Example of a simple policy decision:: + + T = get_clock(MONOTONIC) or get_clock(STEADY) or get_clock() + t = T.now() + +The available clocks always at least include a wrapper for ``time.time()``, +so a final call with no flags can always be used to obtain a working clock. Example of flags of system clocks: @@ -455,6 +480,21 @@ * CLOCK_MONOTONIC_RAW: MONOTONIC | STEADY * gettimeofday(): (no flag) +The clock objects contain other metadata including the clock flags +with additional feature flags above those listed above, the name +of the underlying OS facility, and clock precisions. + +``time.get_clock()`` still chooses a single clock; an enumeration +facility is also required. +The most obvious method is to offer ``time.get_clocks()`` with the +same signature as ``time.get_clock()``, but returning a sequence +of all clocks matching the requested flags. +Requesting no flags would thus enumerate all available clocks, +allowing the caller to make an arbitrary choice amongst them based +on their metadata. + +Example partial implementation: +`clockutils.py `_. One function with a flag: time.monotonic(fallback=True) ------------------------------------------------------- diff --git a/pep-0418/clockutils.py b/pep-0418/clockutils.py new file mode 100644 --- /dev/null +++ b/pep-0418/clockutils.py @@ -0,0 +1,408 @@ +#!/usr/bin/python +# +# Framework to present system clocks by feature, intended to avoid +# the library-as-policy pitfalls of the discussion around PEP 418. +# +# My 2c: +# http://www.gossamer-threads.com/lists/python/dev/977474#977474 +# http://www.gossamer-threads.com/lists/python/dev/977495#977495 +# or: +# http://www.mail-archive.com/python-dev at python.org/msg66174.html +# http://www.mail-archive.com/python-dev at python.org/msg66179.html +# - Cameron Simpson 02apr2012 +# + +from collections import namedtuple +from time import time +import os + +# the module exposing OS clock features +_time = os + +HIGHRES = 0x01 # high resolution +MONOTONIC = 0x02 # never goes backwards +STEADY = 0x04 # never steps; implies MONOTONIC +ADJUSTED = 0x08 # may be adjusted, for example by NTP +WALLCLOCK = 0x10 # tracks real world time, will usually be ADJUSTED too +RUNTIME = 0x20 # track system run time - stops when system suspended +SYNTHETIC = 0x40 # a synthetic clock, computed from other clocks + +def get_clock(flags=0, clocklist=None): + ''' Return a clock based on the supplied `flags`. + The returned clock shall have all the requested flags. + If no clock matches, return None. + ''' + for clock in get_clocks(flags=flags, clocklist=clocklist): + return clock + return None + +def get_clocks(flags=0, clocklist=None): + ''' Yield all clocks matching the supplied `flags`. + The returned clocks shall have all the requested flags. + ''' + if clocklist is None: + clocklist = ALL_CLOCKS + for clock in clocklist: + if clock.flags & flags == flags: + yield clock.factory() + +def monotonic_clock(other_flags=0): + ''' Return a monotonic clock, preferably high resolution. + ''' + return get_clock(MONOTONIC|HIGHRES|other_flags, MONOTONIC_CLOCKS) \ + or get_clock(MONOTONIC|other_flags, MONOTONIC_CLOCKS) + +def steady_clock(other_flags=0): + ''' Return a steady clock, preferably high resolution. + ''' + return get_clock(STEADY|HIGHRES|other_flags, STEADY_CLOCKS) \ + or get_clock(STEADY|other_flags, STEADY_CLOCKS) + +def highres_clock(other_flags=0): + ''' Return a high resolution clock, preferably steady. + ''' + return get_clock(HIGHRES|STEADY|other_flags, HIGHRES_CLOCKS) \ + or get_clock(HIGHRES|other_flags, HIGHRES_CLOCKS) + +_global_monotonic = None + +def monotonic(): + ''' Return the current time according to the default monotonic clock. + ''' + global _global_monotonic + if _global_monotonic is None: + _global_monotonic = monotonic_clock() + if _global_monotonic is None: + raise RunTimeError("no monotonic clock available") + return _global_monotonic.now() + +_global_hires = None + +def highres(): + ''' Return the current time according to the default high resolution clock. + ''' + global _global_hires + if _global_hires is None: + _global_hires = highres() + if _global_hires is None: + raise RunTimeError("no highres clock available") + return _global_hires.now() + +_global_steady = None + +def steady(): + ''' Return the current time according to the default steady clock. + ''' + global _global_steady + if _global_steady is None: + _global_steady = steady() + if _global_steady is None: + raise RunTimeError("no steady clock available") + return _global_steady.now() + +class _Clock_Flags(int): + ''' An int with human friendly str() and repr() for clock flags. + ''' + + _flag_names = ( + 'HIGHRES', + 'MONOTONIC', + 'STEADY', + 'ADJUSTED', + 'WALLCLOCK', + 'RUNTIME', + 'SYNTHETIC', + ) + + def __str__(self): + f = self + G = globals() + names = [] + for name in _Clock_Flags._flag_names: + n = G[name] + if f & n: + names.append(name) + f &= ~n + if f: + names.append('0x%02x' % f) + return '|'.join(names) if names else '0' + + def __repr__(self): + return '<%s %02x %s>' % (self.__class__.__name__, self, self) + +# now assemble the list of platform clocks + +class _Clock(object): + ''' A _Clock is the private base class of clock objects. + A clock has the following mandatory attributes: + .flags Feature flags describing the clock. + A clock may have the following optional attributes: + .epoch If present, the offset from time.time()'s epoch + of this clock's epoch(). Not all clocks have epochs; some + measure elapsed time from an unknown point and only the + difference in two measurements is useful. + .resolution + The resolution of the underlying clock facility's + reporting units. The clock can never be more precise than + this value. The actual accuracy of the reported time may + vary with adjustments and the real accuracy of the + underlying OS clock facility (which in turn may be + dependent on the precision of some hardware clock). + A clock must also supply the following methods: + .now() Report the current time in seconds, a float. + ''' + def __init__(self): + ''' Set instance attributes from class attributes, suitable to + singleton clocks. + ''' + klass = self.__class__ + self.flags = _Clock_Flags(klass.flags) + for attr in 'epoch', 'resolution': + try: + attrval = getattr(klass, attr) + except AttributeError: + pass + else: + setattr(self, attr, attrval) + + def __repr__(self): + props = [self.__class__.__name__] + for attr in sorted( [ attr for attr in dir(self) + if attr + and attr[0].isalpha() + and attr not in ('now',)] ): + props.append("%s=%s" % (attr, getattr(self, attr))) + return "<" + " ".join(props) + ">" + +ClockEntry = namedtuple('ClockEntry', 'flags factory') + +ALL_CLOCKS = [] + +def _SingletonClockEntry( klass ): + ''' Construct a ClockEntry for a Singleton class, typical for system clocks. + ''' + klock = klass() + return ClockEntry( klass.flags, lambda: klock ) + +# always provide good old time.time() +# provide no flags - this is a fallback - totally implementation agnostic +class _TimeDotTimeClock(_Clock): + ''' A clock made from time.time(). + ''' + flags = 0 + epoch = 0 + def now(self): + return time() +ALL_CLOCKS.append( _SingletonClockEntry(_TimeDotTimeClock) ) + +# load system specific clocks here +# in notional order of preference + +if os.name == "nt": + + class _NT_GetSystemTimeAsFileTimeClock(_Clock): + ''' A clock made from GetSystemTimeAsFileTime(). + ''' + flags = WALLCLOCK + epoch = EPOCH_16010101T000000 # 01jan1601 + # a negative value wrt 01jan1970 + resolution = 0.0000001 # 100 nanosecond units + # accuracy HW dependent? + def now(self): + # convert 100-nanosecond intervals since 1601 to UNIX style seconds + return ( _time._GetSystemTimeAsFileTime() / 10000000 + + NT_GetSystemTimeAsFileTimeClock.epoch + ) + ALL_CLOCKS.append( _SingletonClockEntry(_NT_GetSystemTimeAsFileTimeClock) ) + + class _NT_GetTickCount64(_Clock): + ''' Based on + http://msdn.microsoft.com/en-us/library/windows/desktop/ms724411%28v=vs.85%29.aspx + Note this this specificly disavows high resolution. + ''' + flags = RUNTIME|MONOTONIC + resolution = 0.001 + def now(self): + msecs = _time.GetTickCount64() + return msecs / 1000 + ALL_CLOCKS.append( _SingletonClockEntry(_NT_GetTickCount64) ) + +else: + + # presuming clock_gettime() and clock_getres() exposed in the os + # module, along with the clock id names + if hasattr(_time, "clock_gettime"): + + try: + clk_id = _time.CLOCK_REALTIME + except AttributeError: + pass + else: + try: + timespec = _time.clock_getres(clk_id) + except OSError: + pass + else: + class _UNIX_CLOCK_REALTIME(_Clock): + ''' A clock made from clock_gettime(CLOCK_REALTIME). + ''' + epoch = 0 + flags = WALLCLOCK + resolution = timespec.tv_sec + timespec.tv_nsec / 1000000000 + def now(): + timespec = _time.clock_gettime(_time.CLOCK_REALTIME) + return timespec.tv_sec + timespec.tv_nsec / 1000000000 + ALL_CLOCKS.append( _SingletonClockEntry(_UNIX_CLOCK_REALTIME) ) + + try: + clk_id = _time.CLOCK_MONOTONIC + except AttributeError: + pass + else: + try: + timespec = _time.clock_getres(clk_id) + except OSError: + pass + else: + class _UNIX_CLOCK_MONOTONIC(_Clock): + ''' A clock made from clock_gettime(CLOCK_MONOTONIC). + ''' + flags = MONOTONIC|STEADY|ADJUSTED + resolution = timespec.tv_sec + timespec.tv_nsec / 1000000000 + def now(): + timespec = _time.clock_gettime(_time.CLOCK_MONOTONIC) + return timespec.tv_sec + timespec.tv_nsec / 1000000000 + ALL_CLOCKS.append( _SingletonClockEntry(_UNIX_CLOCK_MONOTONIC) ) + + try: + clk_id = _time.CLOCK_MONOTONIC_RAW + except AttributeError: + pass + else: + try: + timespec = _time.clock_getres(clk_id) + except OSError: + pass + else: + class _UNIX_CLOCK_MONOTONIC_RAW(_Clock): + ''' A clock made from clock_gettime(CLOCK_MONOTONIC_RAW). + ''' + flags = MONOTONIC|STEADY + resolution = timespec.tv_sec + timespec.tv_nsec / 1000000000 + def now(): + timespec = _time.clock_gettime(_time.CLOCK_MONOTONIC_RAW) + return timespec.tv_sec + timespec.tv_nsec / 1000000000 + ALL_CLOCKS.append( _SingletonClockEntry(_UNIX_CLOCK_MONOTONIC_RAW) ) + + try: + clk_id = _time.CLOCK_PROCESS_CPUTIME_ID + except AttributeError: + pass + else: + try: + timespec = _time.clock_getres(clk_id) + except OSError: + pass + else: + class _UNIX_CLOCK_PROCESS_CPUTIME_ID(_Clock): + ''' A clock made from clock_gettime(CLOCK_PROCESS_CPUTIME_ID). + ''' + flags = MONOTONIC + resolution = timespec.tv_sec + timespec.tv_nsec / 1000000000 + def now(): + timespec = _time.clock_gettime(_time.CLOCK_PROCESS_CPUTIME_ID) + return timespec.tv_sec + timespec.tv_nsec / 1000000000 + ALL_CLOCKS.append( _SingletonClockEntry(_CLOCK_PROCESS_CPUTIME_ID) ) + + try: + clk_id = _time.CLOCK_THREAD_CPUTIME_ID + except AttributeError: + pass + else: + try: + timespec = _time.clock_getres(clk_id) + except OSError: + pass + else: + class _UNIX_CLOCK_THREAD_CPUTIME_ID(_Clock): + ''' A clock made from clock_gettime(CLOCK_THREAD_CPUTIME_ID). + ''' + flags = MONOTONIC + resolution = timespec.tv_sec + timespec.tv_nsec / 1000000000 + def now(): + timespec = _time.clock_gettime(_time.CLOCK_THREAD_CPUTIME_ID) + return timespec.tv_sec + timespec.tv_nsec / 1000000000 + ALL_CLOCKS.append( _SingletonClockEntry(_CLOCK_CLOCK_THREAD_CPUTIME_ID) ) + + if hasattr(_time, "gettimeofday"): + class _UNIX_gettimeofday(_Clock): + ''' A clock made from gettimeofday(). + ''' + epoch = 0 + flags = WALLCLOCK + resolution = 0.000001 + def now(self): + timeval = _time.gettimeofday() + return timeval.tv_sec + timeval.tv_usec / 1000000 + ALL_CLOCKS.append( _SingletonClockEntry(_UNIX_gettimeofday) ) + + if hasattr(_time, "ftime"): + class _UNIX_ftime(_Clock): + ''' A clock made from ftime(). + ''' + epoch = 0 + flags = WALLCLOCK|ADJUSTED + resolution = 0.001 + def now(self): + timeb = _time.ftime() + return timeb.time + timeb.millitm / 1000 + ALL_CLOCKS.append( _SingletonClockEntry(_UNIX_ftime) ) + +# an example synthetic clock, coming after time.time() +# because I think synthetic clocks should be less desired +# - they tend to have side effects; but perhaps offered anyway because +# they can offer flag combinations not always presented by the system +# clocks + +# a simple synthetic monotonic clock +# may skew with respect to other instances +# Steven D'Aprano wrote a better one +class SyntheticMonotonic(_Clock): + flags = SYNTHETIC|MONOTONIC + def __init__(self, base_clock=None): + _Clock.__init__(self) + if base_clock is None: + base_clock = _TimeDotTimeClock() + self.base_clock = base_clock + for attr in 'epoch', 'resolution': + try: + attrval = getattr(base_clock, attr) + except AttributeError: + pass + else: + setattr(self, attr, attrval) + self.__last = None + self.__base = base_clock + def now(self): + last = self.__last + t = self.__base.now() + if last is None or last < t: + self.__last = t + else: + t = last + return t + +ALL_CLOCKS.append( ClockEntry(SyntheticMonotonic.flags, SyntheticMonotonic) ) + +# With more clocks, these will be ALL_CLOCKS listed in order of preference +# for these types i.e. MONOTONIC_CLOCKS will list only monotonic clocks +# in order of quality (an arbitrary measure, perhaps). +MONOTONIC_CLOCKS = ALL_CLOCKS +HIGHRES_CLOCKS = ALL_CLOCKS +STEADY_CLOCKS = ALL_CLOCKS + +if __name__ == '__main__': + print("ALL_CLOCKS =", repr(ALL_CLOCKS)) + for clock in get_clocks(): + print("clock = %r" % (clock,)) + print(clock.__class__.__doc__) -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 15 13:17:00 2012 From: python-checkins at python.org (kristjan.jonsson) Date: Sun, 15 Apr 2012 13:17:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Make_all_socket?= =?utf8?q?_related_modules_link_with_ws2=5F32=2Elib_on_windows=2C_like?= Message-ID: http://hg.python.org/cpython/rev/1cce16c79de2 changeset: 76317:1cce16c79de2 branch: 3.2 parent: 76301:38f8c779f5f8 user: Kristj?n Valur J?nsson date: Sun Apr 15 11:12:57 2012 +0000 summary: Make all socket related modules link with ws2_32.lib on windows, like _socket does. Some were using the older wsock32.lib. files: PC/VS7.1/select.vcproj | 8 ++++---- PC/VS8.0/select.vcproj | 16 ++++++++-------- PCbuild/select.vcproj | 16 ++++++++-------- PCbuild/xxlimited.vcproj | 12 ++++++------ 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/PC/VS7.1/select.vcproj b/PC/VS7.1/select.vcproj --- a/PC/VS7.1/select.vcproj +++ b/PC/VS7.1/select.vcproj @@ -35,7 +35,7 @@ Name="VCCustomBuildTool"/> @@ -116,7 +116,7 @@ /> @@ -178,7 +178,7 @@ /> @@ -241,7 +241,7 @@ /> @@ -303,7 +303,7 @@ /> @@ -366,7 +366,7 @@ /> @@ -492,7 +492,7 @@ /> @@ -116,7 +116,7 @@ /> @@ -178,7 +178,7 @@ /> @@ -241,7 +241,7 @@ /> @@ -303,7 +303,7 @@ /> @@ -366,7 +366,7 @@ /> @@ -492,7 +492,7 @@ /> @@ -119,7 +119,7 @@ /> @@ -182,7 +182,7 @@ /> @@ -245,7 +245,7 @@ /> @@ -372,7 +372,7 @@ /> http://hg.python.org/cpython/rev/ab0aff639cfb changeset: 76318:ab0aff639cfb parent: 76316:72902ab938e0 parent: 76317:1cce16c79de2 user: Kristj?n Valur J?nsson date: Sun Apr 15 11:14:46 2012 +0000 summary: Merge with 3.2: use ws2_32.lib rather than wsock32.lib on windows. files: PC/VS7.1/select.vcproj | 8 ++++---- PC/VS8.0/select.vcproj | 16 ++++++++-------- PCbuild/select.vcproj | 16 ++++++++-------- PCbuild/xxlimited.vcproj | 12 ++++++------ 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/PC/VS7.1/select.vcproj b/PC/VS7.1/select.vcproj --- a/PC/VS7.1/select.vcproj +++ b/PC/VS7.1/select.vcproj @@ -35,7 +35,7 @@ Name="VCCustomBuildTool"/> @@ -116,7 +116,7 @@ /> @@ -178,7 +178,7 @@ /> @@ -241,7 +241,7 @@ /> @@ -303,7 +303,7 @@ /> @@ -366,7 +366,7 @@ /> @@ -492,7 +492,7 @@ /> @@ -116,7 +116,7 @@ /> @@ -178,7 +178,7 @@ /> @@ -241,7 +241,7 @@ /> @@ -303,7 +303,7 @@ /> @@ -366,7 +366,7 @@ /> @@ -492,7 +492,7 @@ /> @@ -119,7 +119,7 @@ /> @@ -182,7 +182,7 @@ /> @@ -245,7 +245,7 @@ /> @@ -372,7 +372,7 @@ /> http://hg.python.org/cpython/rev/88f8ef5785d7 changeset: 76319:88f8ef5785d7 user: Kristj?n Valur J?nsson date: Sun Apr 15 11:41:32 2012 +0000 summary: Issue #10576: Add a progress callback to gcmodule files: Doc/library/gc.rst | 39 ++++++++- Lib/test/test_gc.py | 136 +++++++++++++++++++++++++++++++- Misc/NEWS | 3 + Modules/gcmodule.c | 80 +++++++++++++++++- 4 files changed, 249 insertions(+), 9 deletions(-) diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -153,8 +153,8 @@ .. versionadded:: 3.1 -The following variable is provided for read-only access (you can mutate its -value but should not rebind it): +The following variables are provided for read-only access (you can mutate the +values but should not rebind them): .. data:: garbage @@ -183,6 +183,41 @@ :const:`DEBUG_UNCOLLECTABLE` is set, in addition all uncollectable objects are printed. +.. data:: callbacks + + A list of callbacks that will be invoked by the garbage collector before and + after collection. The callbacks will be called with two arguments, + :arg:`phase` and :arg:`info`. + + :arg:`phase` can one of two values: + + "start": The garbage collection is about to start. + + "stop": The garbage collection has finished. + + :arg:`info` provides more information for the callback. The following + keys are currently defined: + + "generation": The oldest generation being collected. + + "collected": When :arg:`phase` is "stop", the number of objects + successfully collected. + + "uncollectable": when :arg:`phase` is "stop", the number of objects + that could not be collected and were put in :data:`garbage`. + + Applications can add their own callbacks to this list. The primary + use cases are: + + Gathering statistics about garbage collection, such as how often + various generations are collected, and how long the collection + takes. + + Allowing applications to identify and clear their own uncollectable + types when they appear in :data:`garbage`. + + .. versionadded:: 3.3 + The following constants are provided for use with :func:`set_debug`: diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -32,6 +32,20 @@ # gc collects it. self.wr = weakref.ref(C1055820(666), it_happened) +class Uncollectable(object): + """Create a reference cycle with multiple __del__ methods. + + An object in a reference cycle will never have zero references, + and so must be garbage collected. If one or more objects in the + cycle have __del__ methods, the gc refuses to guess an order, + and leaves the cycle uncollected.""" + def __init__(self, partner=None): + if partner is None: + self.partner = Uncollectable(partner=self) + else: + self.partner = partner + def __del__(self): + pass ### Tests ############################################################################### @@ -528,6 +542,126 @@ self.assertNotIn(b"uncollectable objects at shutdown", stderr) +class GCCallbackTests(unittest.TestCase): + def setUp(self): + # Save gc state and disable it. + self.enabled = gc.isenabled() + gc.disable() + self.debug = gc.get_debug() + gc.set_debug(0) + gc.callbacks.append(self.cb1) + gc.callbacks.append(self.cb2) + + def tearDown(self): + # Restore gc state + del self.visit + gc.callbacks.remove(self.cb1) + gc.callbacks.remove(self.cb2) + gc.set_debug(self.debug) + if self.enabled: + gc.enable() + # destroy any uncollectables + gc.collect() + for obj in gc.garbage: + if isinstance(obj, Uncollectable): + obj.partner = None + del gc.garbage[:] + gc.collect() + + othergarbage = [] + def preclean(self): + # Remove all fluff from the system. Invoke this function + # manually rather than through self.setUp() for maximum + # safety. + self.visit = [] + gc.collect() + garbage, gc.garbage[:] = gc.garbage[:], [] + self.othergarbage.append(garbage) + self.visit = [] + + def cb1(self, phase, info): + self.visit.append((1, phase, dict(info))) + + def cb2(self, phase, info): + self.visit.append((2, phase, dict(info))) + if phase == "stop" and hasattr(self, "cleanup"): + # Clean Uncollectable from garbage + uc = [e for e in gc.garbage if isinstance(e, Uncollectable)] + gc.garbage[:] = [e for e in gc.garbage + if not isinstance(e, Uncollectable)] + for e in uc: + e.partner = None + + def testCollect(self): + self.preclean() + gc.collect() + # Algorithmically verify the contents of self.visit + # because it is long and tortuous. + + # Count the number of visits to each callback + n = [v[0] for v in self.visit] + n1 = [i for i in n if i == 1] + n2 = [i for i in n if i == 2] + self.assertEqual(n1, [1]*2) + self.assertEqual(n2, [2]*2) + + # Count that we got the right number of start and stop callbacks. + n = [v[1] for v in self.visit] + n1 = [i for i in n if i == "start"] + n2 = [i for i in n if i == "stop"] + self.assertEqual(n1, ["start"]*2) + self.assertEqual(n2, ["stop"]*2) + + # Check that we got the right info dict for all callbacks + for v in self.visit: + info = v[2] + self.assertTrue("generation" in info) + self.assertTrue("collected" in info) + self.assertTrue("uncollectable" in info) + + def testCollectGen(self): + self.preclean() + gc.collect(2) + for v in self.visit: + info = v[2] + self.assertEqual(info["generation"], 2) + + def testCollectGarbage(self): + self.preclean() + # Each of these cause four objects to be garbage: Two + # Uncolectables and their instance dicts. + Uncollectable() + Uncollectable() + C1055820(666) + gc.collect() + for v in self.visit: + if v[1] != "stop": + continue + info = v[2] + self.assertEqual(info["collected"], 2) + self.assertEqual(info["uncollectable"], 8) + + # We should now have the Uncollectables in gc.garbage + self.assertEqual(len(gc.garbage), 4) + for e in gc.garbage: + self.assertIsInstance(e, Uncollectable) + + # Now, let our callback handle the Uncollectable instances + self.cleanup=True + self.visit = [] + gc.garbage[:] = [] + gc.collect() + for v in self.visit: + if v[1] != "stop": + continue + info = v[2] + self.assertEqual(info["collected"], 0) + self.assertEqual(info["uncollectable"], 4) + + # Uncollectables should be gone + self.assertEqual(len(gc.garbage), 0) + + class GCTogglingTests(unittest.TestCase): def setUp(self): gc.enable() @@ -681,7 +815,7 @@ try: gc.collect() # Delete 2nd generation garbage - run_unittest(GCTests, GCTogglingTests) + run_unittest(GCTests, GCTogglingTests, GCCallbackTests) finally: gc.set_debug(debug) # test gc.enable() even if GC is disabled by default diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -275,6 +275,9 @@ - Issue #14310: Sockets can now be with other processes on Windows using the api socket.socket.share() and socket.fromshare(). +- Issue #10576: The gc module now has a 'callbacks' member that will get + called when garbage collection takes place. + Build ----- diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -65,14 +65,17 @@ /* Python string to use if unhandled exception occurs */ static PyObject *gc_str = NULL; -/* This is the number of objects who survived the last full collection. It +/* a list of callbacks to be invoked when collection is performed */ +static PyObject *callbacks = NULL; + +/* This is the number of objects that survived the last full collection. It approximates the number of long lived objects tracked by the GC. (by "full collection", we mean a collection of the oldest generation). */ static Py_ssize_t long_lived_total = 0; -/* This is the number of objects who survived all "non-full" collections, +/* This is the number of objects that survived all "non-full" collections, and are awaiting to undergo a full collection for the first time. */ @@ -787,7 +790,7 @@ /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t -collect(int generation) +collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) { int i; Py_ssize_t m = 0; /* # objects collected */ @@ -935,9 +938,64 @@ PyErr_WriteUnraisable(gc_str); Py_FatalError("unexpected exception during garbage collection"); } + + if (n_collected) + *n_collected = m; + if (n_uncollectable) + *n_uncollectable = n; return n+m; } +/* Invoke progress callbacks to notify clients that garbage collection + * is starting or stopping + */ +static void +invoke_gc_callback(const char *phase, int generation, + Py_ssize_t collected, Py_ssize_t uncollectable) +{ + Py_ssize_t i; + PyObject *info = NULL; + + /* we may get called very early */ + if (callbacks == NULL) + return; + /* The local variable cannot be rebound, check it for sanity */ + assert(callbacks != NULL && PyList_CheckExact(callbacks)); + if (PyList_GET_SIZE(callbacks) != 0) { + info = Py_BuildValue("{sisnsn}", + "generation", generation, + "collected", collected, + "uncollectable", uncollectable); + if (info == NULL) { + PyErr_WriteUnraisable(NULL); + return; + } + } + for (i=0; i is @@ -1352,7 +1419,7 @@ n = 0; /* already collecting, don't do anything */ else { collecting = 1; - n = collect(NUM_GENERATIONS - 1); + n = collect_with_callback(NUM_GENERATIONS - 1); collecting = 0; } @@ -1389,6 +1456,7 @@ Py_XDECREF(bytes); } } + Py_CLEAR(callbacks); } /* for debugging */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 15:39:57 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 15 Apr 2012 15:39:57 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_last_comments?= Message-ID: http://hg.python.org/peps/rev/629341c49f1b changeset: 4251:629341c49f1b user: Victor Stinner date: Sun Apr 15 15:39:48 2012 +0200 summary: PEP 418: Add last comments * Indicate if a clock is system-wide or process-wide * Add time.metronomic() alternative name * Explain why "steady" name was not chosen files: pep-0418.txt | 57 ++++++++++++++++++++++----------------- 1 files changed, 32 insertions(+), 25 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -111,10 +111,17 @@ time.monotonic() ^^^^^^^^^^^^^^^^ -Monotonic clock, cannot go backward. It is not affected by system -clock updates. The reference point of the returned value is -undefined, so that only the difference between the results of -consecutive calls is valid. +Monotonic clock, cannot go backward. It is not affected by system clock +updates. The reference point of the returned value is undefined, so that only +the difference between the results of consecutive calls is valid. + +On Windows older than Vista, ``time.monotonic()`` detects ``GetTickCount()`` +integer overflow (32 bits, roll-over after 49.7 days): it increases a delta by +2\ :sup:`32` each time than an overflow is detected. The delta is stored in +the process-local state and so the value of ``time.monotonic()`` may be +different in two Python processes running for more than 49 days. On more recent +versions of Windows and on other operating systems, ``time.monotonic()`` is +system-wide. Availability: Windows, Mac OS X, Unix, Solaris. Not available on GNU/Hurd. @@ -160,21 +167,14 @@ has a better precision than ``GetTickCount()``. It is not reliable and has too many issues. -``time.monotonic()`` detects ``GetTickCount()`` integer overflow (32 bits, -roll-over after 49.7 days): it increases a delta by 2\ :sup:`32` each time -than an overflow is detected. The delta is stored in the process-local -state and so the value of ``time.monotonic()`` may be different in two -Python processes running for more than 49 days. - time.perf_counter() ^^^^^^^^^^^^^^^^^^^ -Performance counter used for benchmarking. It is monotonic, -i.e. cannot go backward. It does include time elapsed during sleep. -The reference point of the returned value is undefined, so that only -the difference between the results of consecutive calls is valid and -is number of seconds. +Performance counter used for benchmarking. It is monotonic, i.e. cannot go +backward. It does include time elapsed during sleep and is system-wide. The +reference point of the returned value is undefined, so that only the difference +between the results of consecutive calls is valid and is number of seconds. Pseudo-code:: @@ -208,10 +208,10 @@ time.process_time() ^^^^^^^^^^^^^^^^^^^ -Process time used for profiling: sum of the kernel and user-space CPU -time. It does not include time elapsed during sleep. The reference -point of the returned value is undefined, so that only the difference -between the results of consecutive calls is valid. +Process time used for profiling: sum of the kernel and user-space CPU time. It +does not include time elapsed during sleep. It is process-wide by definition. +The reference point of the returned value is undefined, so that only the +difference between the results of consecutive calls is valid. Pseudo-code [#pseudo]_:: @@ -264,7 +264,7 @@ The system time is the "wall clock". It can be set manually by the system administrator or automatically by a NTP daemon. It can jump -backward and forward. It is not monotonic. +backward and forward. It is system-wide but not monotonic. It is available on all platforms and cannot fail. @@ -347,15 +347,15 @@ ^^^^^^^^^^^^ On Unix, return the current processor time as a floating point number -expressed in seconds. The precision, and in fact the very definition -of the meaning of "processor time", depends on that of the C function -of the same name, but in any case, this is the function to use for -benchmarking Python or timing algorithms. +expressed in seconds. It is process-wide by definition. The precision, and in +fact the very definition of the meaning of "processor time", depends on that of +the C function of the same name, but in any case, this is the function to use +for benchmarking Python or timing algorithms. On Windows, this function returns wall-clock seconds elapsed since the first call to this function, as a floating point number, based on the Win32 function ``QueryPerformanceCounter()``. The resolution is -typically better than one microsecond. +typically better than one microsecond. It is system-wide. Pseudo-code [#pseudo]_:: @@ -391,12 +391,19 @@ time.monotonic(): * time.counter() +* time.metronomic() * time.seconds() * time.steady() * time.timeout_clock() * time.wallclock(): it is not the system time aka the "wall clock", but a monotonic clock with an unspecified starting point +"steady" is ambiguous: it means different things to different people. For +example, on Linux, CLOCK_MONOTONIC is adjusted. If we uses the real time as the +reference clock, we may say that CLOCK_MONOTONIC is steady. But +CLOCK_MONOTONIC gets suspended on system suspend, whereas real time includes +any time spent in suspend. + The name "time.try_monotonic()" was also proposed when time.monotonic() was falling back to the system clock when no monotonic clock was available. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 15 16:14:43 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 15 Apr 2012 16:14:43 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzODg5?= =?utf8?q?=3A_On_MSVC_builds=2C_set_FPU_control_word_at_runtime_for_all_st?= =?utf8?q?ring?= Message-ID: http://hg.python.org/cpython/rev/dfc9a98a5fef changeset: 76320:dfc9a98a5fef branch: 3.2 parent: 76317:1cce16c79de2 user: Mark Dickinson date: Sun Apr 15 15:10:56 2012 +0100 summary: Issue #13889: On MSVC builds, set FPU control word at runtime for all string <-> float conversions. Patch by Samuel Iseli and Stefan Krah. files: Include/pyport.h | 24 ++++++++++++++++++++++++ Misc/NEWS | 4 ++++ 2 files changed, 28 insertions(+), 0 deletions(-) diff --git a/Include/pyport.h b/Include/pyport.h --- a/Include/pyport.h +++ b/Include/pyport.h @@ -557,6 +557,30 @@ _Py_set_387controlword(old_387controlword) #endif +/* get and set x87 control word for VisualStudio/x86 */ +#if defined(_MSC_VER) && !defined(_WIN64) /* x87 not supported in 64-bit */ +#define HAVE_PY_SET_53BIT_PRECISION 1 +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned int old_387controlword, new_387controlword, out_387controlword +/* We use the __control87_2 function to set only the x87 control word. + The SSE control word is unaffected. */ +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + __control87_2(0, 0, &old_387controlword, NULL); \ + new_387controlword = \ + (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \ + if (new_387controlword != old_387controlword) \ + __control87_2(new_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + do { \ + if (new_387controlword != old_387controlword) \ + __control87_2(old_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } while (0) +#endif + /* default definitions are empty */ #ifndef HAVE_PY_SET_53BIT_PRECISION #define _Py_SET_53BIT_PRECISION_HEADER diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #13889: Check and (if necessary) set FPU control word before calling + any of the dtoa.c string <-> float conversion functions, on MSVC builds of + Python. This fixes issues when embedding Python in a Delphi app. + - Issue #14474: Save and restore exception state in thread.start_new_thread() while writing error message if the thread leaves a unhandled exception. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 16:14:43 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 15 Apr 2012 16:14:43 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2313889=3A_Merge_fix_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/7eca620feb10 changeset: 76321:7eca620feb10 parent: 76319:88f8ef5785d7 parent: 76320:dfc9a98a5fef user: Mark Dickinson date: Sun Apr 15 15:12:37 2012 +0100 summary: Issue #13889: Merge fix from 3.2. files: Include/pyport.h | 24 ++++++++++++++++++++++++ Misc/NEWS | 4 ++++ 2 files changed, 28 insertions(+), 0 deletions(-) diff --git a/Include/pyport.h b/Include/pyport.h --- a/Include/pyport.h +++ b/Include/pyport.h @@ -557,6 +557,30 @@ _Py_set_387controlword(old_387controlword) #endif +/* get and set x87 control word for VisualStudio/x86 */ +#if defined(_MSC_VER) && !defined(_WIN64) /* x87 not supported in 64-bit */ +#define HAVE_PY_SET_53BIT_PRECISION 1 +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned int old_387controlword, new_387controlword, out_387controlword +/* We use the __control87_2 function to set only the x87 control word. + The SSE control word is unaffected. */ +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + __control87_2(0, 0, &old_387controlword, NULL); \ + new_387controlword = \ + (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \ + if (new_387controlword != old_387controlword) \ + __control87_2(new_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + do { \ + if (new_387controlword != old_387controlword) \ + __control87_2(old_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } while (0) +#endif + /* default definitions are empty */ #ifndef HAVE_PY_SET_53BIT_PRECISION #define _Py_SET_53BIT_PRECISION_HEADER diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #13889: Check and (if necessary) set FPU control word before calling + any of the dtoa.c string <-> float conversion functions, on MSVC builds of + Python. This fixes issues when embedding Python in a Delphi app. + - Issue #2377: Make importlib the implementation of __import__(). - Issue #1559549: ImportError now has 'name' and 'path' attributes that are set -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 16:19:18 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 15 Apr 2012 16:19:18 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzODg5?= =?utf8?q?=3A_On_MSVC_builds=2C_set_FPU_control_word_at_runtime_for_all_st?= =?utf8?q?ring?= Message-ID: http://hg.python.org/cpython/rev/bf3b77722c9f changeset: 76322:bf3b77722c9f branch: 2.7 parent: 76295:225126c9d4b5 user: Mark Dickinson date: Sun Apr 15 15:19:06 2012 +0100 summary: Issue #13889: On MSVC builds, set FPU control word at runtime for all string <-> float conversions. Patch by Samuel Iseli and Stefan Krah. files: Include/pyport.h | 24 ++++++++++++++++++++++++ Misc/NEWS | 4 ++++ 2 files changed, 28 insertions(+), 0 deletions(-) diff --git a/Include/pyport.h b/Include/pyport.h --- a/Include/pyport.h +++ b/Include/pyport.h @@ -549,6 +549,30 @@ _Py_set_387controlword(old_387controlword) #endif +/* get and set x87 control word for VisualStudio/x86 */ +#if defined(_MSC_VER) && !defined(_WIN64) /* x87 not supported in 64-bit */ +#define HAVE_PY_SET_53BIT_PRECISION 1 +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned int old_387controlword, new_387controlword, out_387controlword +/* We use the __control87_2 function to set only the x87 control word. + The SSE control word is unaffected. */ +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + __control87_2(0, 0, &old_387controlword, NULL); \ + new_387controlword = \ + (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \ + if (new_387controlword != old_387controlword) \ + __control87_2(new_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + do { \ + if (new_387controlword != old_387controlword) \ + __control87_2(old_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } while (0) +#endif + /* default definitions are empty */ #ifndef HAVE_PY_SET_53BIT_PRECISION #define _Py_SET_53BIT_PRECISION_HEADER diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,10 @@ Core and Builtins ----------------- +- Issue #13889: Check and (if necessary) set FPU control word before calling + any of the dtoa.c string <-> float conversion functions, on MSVC builds of + Python. This fixes issues when embedding Python in a Delphi app. + - Issue #14505: Fix file descriptor leak when deallocating file objects created with PyFile_FromString(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 17:06:45 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 15 Apr 2012 17:06:45 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418?= Message-ID: http://hg.python.org/peps/rev/f2bb3f74298a changeset: 4252:f2bb3f74298a user: Victor Stinner date: Sun Apr 15 17:06:07 2012 +0200 summary: PEP 418 * time.perf_counter() is not necessary monotonic; format code * Replace system clock by system time to reuse the expression of the glossary * If CLOCK_HIGHRES is available, time.monotonic() only uses it and does not fallback to CLOCK_MONOTONIC because CLOCK_MONOTONIC may not be available at the same time * Rewrite time.perf_counter(), time.process_time() and time.time() doc * Reorder "fallback to system time" alternatives files: pep-0418.txt | 307 ++++++++++++++++++++------------------ 1 files changed, 160 insertions(+), 147 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -21,19 +21,20 @@ Rationale ========= -If a program uses the system clock to schedule events or to implement +If a program uses the system time to schedule events or to implement a timeout, it will not run events at the right moment or stop the -timeout too early or too late when the system clock is set manually or +timeout too early or too late when the system time is set manually or adjusted automatically by NTP. A monotonic clock should be used -instead to not be affected by system clock updates. +instead to not be affected by system time updates: +``time.monotonic()``. To measure the performance of a function, ``time.clock()`` can be used but it is very different on Windows and on Unix. On Windows, ``time.clock()`` includes time elapsed during sleep, whereas it does not on Unix. ``time.clock()`` precision is very good on Windows, but -very bad on Unix. The new ``time.perf_counter()`` function can be +very bad on Unix. The new ``time.perf_counter()`` function should be used instead to always get the most precise performance counter with a -portable behaviour. +portable behaviour (ex: include time spend during sleep). To measure CPU time, Python does not provide directly a portable function. ``time.clock()`` can be used on Unix, but it has a bad @@ -60,18 +61,18 @@ Users of new functions: - * time.monotonic(): concurrent.futures, multiprocessing, queue, subprocess, - telnet and threading modules to implement timeout - * time.perf_counter(): trace and timeit modules, pybench program - * time.process_time(): profile module - * time.get_clock_info(): pybench program to display information about the - timer like the precision or the resolution +* time.monotonic(): concurrent.futures, multiprocessing, queue, subprocess, + telnet and threading modules to implement timeout +* time.perf_counter(): trace and timeit modules, pybench program +* time.process_time(): profile module +* time.get_clock_info(): pybench program to display information about the + timer like the precision or the resolution -The ``time.clock()`` function is deprecated by this PEP because it is not +The ``time.clock()`` function is deprecated because it is not portable: it behaves differently depending on the operating system. -``time.perf_counter()`` or ``time.process_time()`` should be used instead, -depending on your requirements. ``time.clock()`` is marked as deprecated but -is not planned for removal. +``time.perf_counter()`` or ``time.process_time()`` should be used +instead, depending on your requirements. ``time.clock()`` is marked as +deprecated but is not planned for removal. Python functions @@ -83,47 +84,51 @@ time.get_clock_info(name) ^^^^^^^^^^^^^^^^^^^^^^^^^ -Get information on the specified clock. Supported clocks: +Get information on the specified clock. Supported clock names: -* "clock": time.clock() -* "monotonic": time.monotonic() -* "perf_counter": time.perf_counter() -* "process_time": time.process_time() -* "time": time.time() +* ``"clock"``: ``time.clock()`` +* ``"monotonic"``: ``time.monotonic()`` +* ``"perf_counter"``: ``time.perf_counter()`` +* ``"process_time"``: ``time.process_time()`` +* ``"time"``: ``time.time()`` Return a dictionary with the following keys: * Mandatory keys: - * "implementation" (str): name of the underlying operating system - function. Examples: "QueryPerformanceCounter()", - "clock_gettime(CLOCK_REALTIME)". - * "resolution" (float): resolution in seconds of the clock - * "is_monotonic" (bool): True if the clock cannot go backward + * ``"implementation"`` (str): name of the underlying operating system + function. Examples: ``"QueryPerformanceCounter()"``, + ``"clock_gettime(CLOCK_REALTIME)"``. + * ``"resolution"`` (float): resolution in seconds of the clock. + * ``"is_monotonic"`` (bool): True if the clock cannot go backward. * Optional keys: - * "precision" (float): precision in seconds of the clock - * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a - NTP daemon) + * ``"precision"`` (float): precision in seconds of the clock + reported by the operating system. + * ``"is_adjusted"`` (bool): True if the clock is adjusted (e.g. by a + NTP daemon). time.monotonic() ^^^^^^^^^^^^^^^^ -Monotonic clock, cannot go backward. It is not affected by system clock -updates. The reference point of the returned value is undefined, so that only -the difference between the results of consecutive calls is valid. +Monotonic clock, i.e. cannot go backward. It is not affected by system +clock updates. The reference point of the returned value is +undefined, so that only the difference between the results of +consecutive calls is valid and is a number of seconds. -On Windows older than Vista, ``time.monotonic()`` detects ``GetTickCount()`` -integer overflow (32 bits, roll-over after 49.7 days): it increases a delta by -2\ :sup:`32` each time than an overflow is detected. The delta is stored in -the process-local state and so the value of ``time.monotonic()`` may be -different in two Python processes running for more than 49 days. On more recent -versions of Windows and on other operating systems, ``time.monotonic()`` is +On Windows versions older than Vista, ``time.monotonic()`` detects +``GetTickCount()`` integer overflow (32 bits, roll-over after 49.7 +days): it increases a delta by 2\ :sup:`32` each time than an overflow +is detected. The delta is stored in the process-local state and so +the value of ``time.monotonic()`` may be different in two Python +processes running for more than 49 days. On more recent versions of +Windows and on other operating systems, ``time.monotonic()`` is system-wide. -Availability: Windows, Mac OS X, Unix, Solaris. Not available on GNU/Hurd. +Availability: Windows, Mac OS X, Unix, Solaris. Not available on +GNU/Hurd. Pseudo-code [#pseudo]_:: @@ -151,16 +156,13 @@ return _time.mach_absolute_time() * monotonic.factor monotonic.factor = None - elif hasattr(time, "clock_gettime"): + elif hasattr(time, "clock_gettime") and hasattr(time, "CLOCK_HIGHRES"): def monotonic(): - if monotonic.use_clock_highres: - try: - time.clock_gettime(time.CLOCK_HIGHRES) - except OSError: - monotonic.use_clock_highres = False + return time.clock_gettime(time.CLOCK_HIGHRES) + + elif hasattr(time, "clock_gettime") and hasattr(time, "CLOCK_MONOTONIC"): + def monotonic(): return time.clock_gettime(time.CLOCK_MONOTONIC) - monotonic.use_clock_highres = (hasattr(time, 'clock_gettime') - and hasattr(time, 'CLOCK_HIGHRES')) On Windows, ``QueryPerformanceCounter()`` is not used even though it @@ -171,29 +173,30 @@ time.perf_counter() ^^^^^^^^^^^^^^^^^^^ -Performance counter used for benchmarking. It is monotonic, i.e. cannot go -backward. It does include time elapsed during sleep and is system-wide. The -reference point of the returned value is undefined, so that only the difference -between the results of consecutive calls is valid and is number of seconds. +Performance counter with the highest available precision to measure a +duration. It does include time elapsed during sleep and is +system-wide. The reference point of the returned value is undefined, +so that only the difference between the results of consecutive calls +is valid and is a number of seconds. Pseudo-code:: def perf_counter(): if perf_counter.use_performance_counter: - if perf_counter.perf_frequency is None: + if perf_counter.performance_frequency is None: try: - perf_counter.perf_frequency = float(_time.QueryPerformanceFrequency()) + perf_counter.performance_frequency = _time.QueryPerformanceFrequency() except OSError: # QueryPerformanceFrequency() fails if the installed # hardware does not support a high-resolution performance # counter perf_counter.use_performance_counter = False else: - return _time.QueryPerformanceCounter() / perf_counter.perf_frequency + return _time.QueryPerformanceCounter() / perf_counter.performance_frequency else: - return _time.QueryPerformanceCounter() / perf_counter.perf_frequency + return _time.QueryPerformanceCounter() / perf_counter.performance_frequency if perf_counter.use_monotonic: - # Monotonic clock is preferred over system clock + # The monotonic clock is preferred over the system time try: return time.monotonic() except OSError: @@ -201,17 +204,20 @@ return time.time() perf_counter.use_performance_counter = (os.name == 'nt') if perf_counter.use_performance_counter: - perf_counter.perf_frequency = None + perf_counter.performance_frequency = None perf_counter.use_monotonic = hasattr(time, 'monotonic') time.process_time() ^^^^^^^^^^^^^^^^^^^ -Process time used for profiling: sum of the kernel and user-space CPU time. It -does not include time elapsed during sleep. It is process-wide by definition. -The reference point of the returned value is undefined, so that only the -difference between the results of consecutive calls is valid. +Sum of the system and user CPU time of the current process. It does +not include time elapsed during sleep. It is process-wide by +definition. The reference point of the returned value is undefined, +so that only the difference between the results of consecutive calls +is valid. + +It is available on all platforms. Pseudo-code [#pseudo]_:: @@ -262,9 +268,9 @@ time.time() ^^^^^^^^^^^ -The system time is the "wall clock". It can be set manually by the -system administrator or automatically by a NTP daemon. It can jump -backward and forward. It is system-wide but not monotonic. +The system time which is usually the civil time. It is system-wide by +definition. It can be set manually by the system administrator or +automatically by a NTP daemon. It is available on all platforms and cannot fail. @@ -347,10 +353,11 @@ ^^^^^^^^^^^^ On Unix, return the current processor time as a floating point number -expressed in seconds. It is process-wide by definition. The precision, and in -fact the very definition of the meaning of "processor time", depends on that of -the C function of the same name, but in any case, this is the function to use -for benchmarking Python or timing algorithms. +expressed in seconds. It is process-wide by definition. The precision, +and in fact the very definition of the meaning of "processor time", +depends on that of the C function of the same name, but in any case, +this is the function to use for benchmarking Python or timing +algorithms. On Windows, this function returns wall-clock seconds elapsed since the first call to this function, as a floating point number, based on the @@ -385,35 +392,33 @@ Alternatives: API design ======================== -Other names for new functions ------------------------------ - -time.monotonic(): +Other names for time.monotonic() +-------------------------------- * time.counter() * time.metronomic() * time.seconds() -* time.steady() +* time.steady(): "steady" is ambiguous: it means different things to + different people. For example, on Linux, CLOCK_MONOTONIC is + adjusted. If we uses the real time as the reference clock, we may + say that CLOCK_MONOTONIC is steady. But CLOCK_MONOTONIC gets + suspended on system suspend, whereas real time includes any time + spent in suspend. * time.timeout_clock() -* time.wallclock(): it is not the system time aka the "wall clock", - but a monotonic clock with an unspecified starting point +* time.wallclock(): time.monotonic() is not the system time aka the + "wall clock", but a monotonic clock with an unspecified starting + point. -"steady" is ambiguous: it means different things to different people. For -example, on Linux, CLOCK_MONOTONIC is adjusted. If we uses the real time as the -reference clock, we may say that CLOCK_MONOTONIC is steady. But -CLOCK_MONOTONIC gets suspended on system suspend, whereas real time includes -any time spent in suspend. +The name "time.try_monotonic()" was also proposed for an older +proposition of time.monotonic() which was falling back to the system +time when no monotonic clock was available. -The name "time.try_monotonic()" was also proposed when -time.monotonic() was falling back to the system clock when no -monotonic clock was available. +Other names for time.perf_counter() +----------------------------------- -time.perf_counter(): - - * time.hires() - * time.highres() - * time.timer() - +* time.hires() +* time.highres() +* time.timer() Only expose operating system clocks ----------------------------------- @@ -424,20 +429,48 @@ to Python 3.3 for example. -Fallback to system clock ------------------------- +time.monotonic(): Fallback to system time +----------------------------------------- If no monotonic clock is available, time.monotonic() falls back to the -system clock. +system time. Issues: * It is hard to define correctly such function in the documentation: - is it monotonic? is it steady? is it adjusted? + is it monotonic? Is it steady? Is it adjusted? * Some user want to decide what to do when no monotonic clock is available: use another clock, display an error, or do something else? +Different APIs were proposed to define such function. + +One function with a flag: time.monotonic(fallback=True) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* time.monotonic(fallback=True) falls back to the system time if no + monotonic clock is available or if the monotonic clock failed. +* time.monotonic(fallback=False) raises OSError if monotonic clock + fails and NotImplementedError if the system does not provide a + monotonic clock + +A keyword argument that gets passed as a constant in the caller is +usually poor API. + +Raising NotImplementedError for a function is something uncommon in +Python and should be avoided. + + +One time.monotonic() function, no flag +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +time.monotonic() returns (time: float, is_monotonic: bool). + +An alternative is to use a function attribute: +time.monotonic.is_monotonic. The attribute value would be None before +the first call to time.monotonic(). + + Choosing the clock from a list of constraints --------------------------------------------- @@ -503,32 +536,6 @@ Example partial implementation: `clockutils.py `_. -One function with a flag: time.monotonic(fallback=True) -------------------------------------------------------- - -* time.monotonic(fallback=True) falls back to the system clock if no - monotonic clock is available or if the monotonic clock failed. -* time.monotonic(fallback=False) raises OSError if monotonic clock - fails and NotImplementedError if the system does not provide a - monotonic clock - -"A keyword argument that gets passed as a constant in the caller is -usually poor API." - -Raising NotImplementedError for a function is something uncommon in -Python and should be avoided. - - -One function, no flag ---------------------- - -time.monotonic() returns (time: float, is_monotonic: bool). - -An alternative is to use a function attribute: -time.monotonic.is_monotonic. The attribute value would be None before -the first call to time.monotonic(). - - Working around operating system bugs? ------------------------------------- @@ -1127,8 +1134,8 @@ On Solaris, gethrtime() is the same as clock_gettime(CLOCK_MONOTONIC). -System clocks -------------- +System Time +----------- ========================= =============== ============= =============== Name Resolution Include sleep Include suspend @@ -1159,7 +1166,7 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The system time can be read using GetSystemTimeAsFileTime(), ftime() and -time(). The precision of the system clock can be read using +time(). The precision of the system time can be read using GetSystemTimeAdjustment(). Read the `GetSystemTimeAsFileTime() documentation @@ -1171,7 +1178,7 @@ ^^^^^^^^^^^^^^^^^^^ gettimeofday(), ftime(), time() and clock_gettime(CLOCK_REALTIME) return -the system clock. The precision of CLOCK_REALTIME can be read using +the system time. The precision of CLOCK_REALTIME can be read using clock_getres(). The system time can be set using settimeofday() or @@ -1224,8 +1231,9 @@ Functions ^^^^^^^^^ -* Windows: GetProcessTimes(). The precision can be read using - GetSystemTimeAdjustment(). +* Windows: `GetProcessTimes() + `_. + The precision can be read using GetSystemTimeAdjustment(). * clock_gettime(CLOCK_PROCESS_CPUTIME_ID): High-resolution per-process timer from the CPU. The precision can be read using clock_getres(). * clock(). The precision is 1 / CLOCKS_PER_SEC. @@ -1280,9 +1288,9 @@ Functions ^^^^^^^^^ -* Windows: GetThreadTimes(). The precision can be read using - GetSystemTimeAdjustment(). `MSDN documentation of GetThreadTimes() +* Windows: `GetThreadTimes() `_. + The precision can be read using GetSystemTimeAdjustment(). * clock_gettime(CLOCK_THREAD_CPUTIME_ID): Thread-specific CPU-time clock. The precision can be read using of clock_getres(). @@ -1312,11 +1320,11 @@ Sleep ----- -Suspend execution of the process for the given number of seconds. Sleep is not -affected by system clock update. Sleep is paused during system suspend. For -example, if a process sleeps for 60 seconds and the system is suspended for 30 -seconds in the middle of the sleep, the sleep duration is 90 seconds in the -real time. +Suspend execution of the process for the given number of seconds. +Sleep is not affected by system time updates. Sleep is paused during +system suspend. For example, if a process sleeps for 60 seconds and +the system is suspended for 30 seconds in the middle of the sleep, the +sleep duration is 90 seconds in the real time. Sleep can be interrupted by a signal: the function fails with EINTR. @@ -1348,12 +1356,12 @@ Functions ^^^^^^^^^ - * sleep(seconds) - * usleep(microseconds) - * nanosleep(nanoseconds, remaining): - `Linux manpage of nanosleep() - `_ - * delay(milliseconds) +* sleep(seconds) +* usleep(microseconds) +* nanosleep(nanoseconds, remaining): + `Linux manpage of nanosleep() + `_ +* delay(milliseconds) clock_nanosleep @@ -1390,19 +1398,19 @@ Other functions ^^^^^^^^^^^^^^^ - * poll(), epoll() - * sigtimedwait(). POSIX: "If the Monotonic Clock option is supported, - the CLOCK_MONOTONIC clock shall be used to measure the time - interval specified by the timeout argument." - * pthread_cond_timedwait(), pthread_condattr_setclock(). "The default - value of the clock attribute shall refer to the system clock." - * sem_timedwait(): "If the Timers option is supported, the timeout - shall be based on the CLOCK_REALTIME clock. If the Timers option is - not supported, the timeout shall be based on the system clock as - returned by the time() function. The precision of the timeout - shall be the precision of the clock on which it is based." - * WaitForSingleObject(): use the same timer than GetTickCount() with - the same precision. +* poll(), epoll() +* sigtimedwait(). POSIX: "If the Monotonic Clock option is supported, + the CLOCK_MONOTONIC clock shall be used to measure the time + interval specified by the timeout argument." +* pthread_cond_timedwait(), pthread_condattr_setclock(). "The default + value of the clock attribute shall refer to the system time." +* sem_timedwait(): "If the Timers option is supported, the timeout + shall be based on the CLOCK_REALTIME clock. If the Timers option is + not supported, the timeout shall be based on the system time as + returned by the time() function. The precision of the timeout + shall be the precision of the clock on which it is based." +* WaitForSingleObject(): use the same timer than GetTickCount() with + the same precision. System Standby @@ -1506,7 +1514,7 @@ for Windows `_ * `clockspeed `_ uses a hardware tick - counter to compensate for a persistently fast or slow system clock + counter to compensate for a persistently fast or slow system time * `Retrieving system time `_ lists hardware clocks and time functions with their resolution and -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 15 17:43:46 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 15 Apr 2012 17:43:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Issue_13496=3A_?= =?utf8?q?Fix_bisect=2Ebisect_overflow_bug_for_large_collections=2E?= Message-ID: http://hg.python.org/cpython/rev/35a3a7e0d66d changeset: 76323:35a3a7e0d66d branch: 3.2 parent: 76320:dfc9a98a5fef user: Mark Dickinson date: Sun Apr 15 16:30:35 2012 +0100 summary: Issue 13496: Fix bisect.bisect overflow bug for large collections. files: Lib/test/test_bisect.py | 7 +++++++ Misc/NEWS | 3 +++ Modules/_bisectmodule.c | 10 ++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -122,6 +122,13 @@ self.assertRaises(ValueError, mod.insort_left, [1, 2, 3], 5, -1, 3), self.assertRaises(ValueError, mod.insort_right, [1, 2, 3], 5, -1, 3), + def test_large_range(self): + # Issue 13496 + mod = self.module + data = range(sys.maxsize-1) + self.assertEqual(mod.bisect_left(data, sys.maxsize-3), sys.maxsize-3) + self.assertEqual(mod.bisect_right(data, sys.maxsize-3), sys.maxsize-2) + def test_random(self, n=25): from random import randrange for i in range(n): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -43,6 +43,9 @@ Library ------- +- Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied + to a collection of size > sys.maxsize / 2. + - Issue #14399: zipfile now recognizes that the archive has been modified even if only the comment is changed. In addition, the TypeError that results from trying to set a non-binary value as a comment is now now raised at the time diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -21,7 +21,10 @@ return -1; } while (lo < hi) { - mid = (lo + hi) / 2; + /* The (size_t)cast ensures that the addition and subsequent division + are performed as unsigned operations, avoiding difficulties from + signed overflow. (See issue 13496.) */ + mid = ((size_t)lo + hi) / 2; litem = PySequence_GetItem(list, mid); if (litem == NULL) return -1; @@ -121,7 +124,10 @@ return -1; } while (lo < hi) { - mid = (lo + hi) / 2; + /* The (size_t)cast ensures that the addition and subsequent division + are performed as unsigned operations, avoiding difficulties from + signed overflow. (See issue 13496.) */ + mid = ((size_t)lo + hi) / 2; litem = PySequence_GetItem(list, mid); if (litem == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 17:43:47 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 15 Apr 2012 17:43:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2313496=3A_Merge_from_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/1a9252280f07 changeset: 76324:1a9252280f07 parent: 76321:7eca620feb10 parent: 76323:35a3a7e0d66d user: Mark Dickinson date: Sun Apr 15 16:32:04 2012 +0100 summary: Issue #13496: Merge from 3.2 files: Lib/test/test_bisect.py | 7 +++++++ Misc/NEWS | 3 +++ Modules/_bisectmodule.c | 10 ++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -122,6 +122,13 @@ self.assertRaises(ValueError, mod.insort_left, [1, 2, 3], 5, -1, 3), self.assertRaises(ValueError, mod.insort_right, [1, 2, 3], 5, -1, 3), + def test_large_range(self): + # Issue 13496 + mod = self.module + data = range(sys.maxsize-1) + self.assertEqual(mod.bisect_left(data, sys.maxsize-3), sys.maxsize-3) + self.assertEqual(mod.bisect_right(data, sys.maxsize-3), sys.maxsize-2) + def test_random(self, n=25): from random import randrange for i in range(n): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,9 @@ Library ------- +- Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied + to a collection of size > sys.maxsize / 2. + - Have importlib take advantage of ImportError's new 'name' and 'path' attributes. diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -21,7 +21,10 @@ return -1; } while (lo < hi) { - mid = (lo + hi) / 2; + /* The (size_t)cast ensures that the addition and subsequent division + are performed as unsigned operations, avoiding difficulties from + signed overflow. (See issue 13496.) */ + mid = ((size_t)lo + hi) / 2; litem = PySequence_GetItem(list, mid); if (litem == NULL) return -1; @@ -123,7 +126,10 @@ return -1; } while (lo < hi) { - mid = (lo + hi) / 2; + /* The (size_t)cast ensures that the addition and subsequent division + are performed as unsigned operations, avoiding difficulties from + signed overflow. (See issue 13496.) */ + mid = ((size_t)lo + hi) / 2; litem = PySequence_GetItem(list, mid); if (litem == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 17:43:47 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 15 Apr 2012 17:43:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Issue_13496=3A_?= =?utf8?q?Fix_bisect=2Ebisect_overflow_bug_for_large_collections=2E?= Message-ID: http://hg.python.org/cpython/rev/709af2d0e862 changeset: 76325:709af2d0e862 branch: 2.7 parent: 76322:bf3b77722c9f user: Mark Dickinson date: Sun Apr 15 16:43:19 2012 +0100 summary: Issue 13496: Fix bisect.bisect overflow bug for large collections. files: Lib/test/test_bisect.py | 7 +++++++ Misc/NEWS | 3 +++ Modules/_bisectmodule.c | 13 +++++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -122,6 +122,13 @@ self.assertRaises(ValueError, mod.insort_left, [1, 2, 3], 5, -1, 3), self.assertRaises(ValueError, mod.insort_right, [1, 2, 3], 5, -1, 3), + def test_large_range(self): + # Issue 13496 + mod = self.module + data = xrange(sys.maxsize-1) + self.assertEqual(mod.bisect_left(data, sys.maxsize-3), sys.maxsize-3) + self.assertEqual(mod.bisect_right(data, sys.maxsize-3), sys.maxsize-2) + def test_random(self, n=25): from random import randrange for i in xrange(n): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,9 @@ Library ------- +- Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied + to a collection of size > sys.maxsize / 2. + - Issue #14399: zipfile now recognizes that the archive has been modified even if only the comment is changed. As a consequence of this fix, ZipFile is now a new style class. diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -21,7 +21,13 @@ return -1; } while (lo < hi) { - mid = (lo + hi) / 2; + /* The (size_t)cast ensures that the addition and subsequent division + are performed as unsigned operations, avoiding difficulties from + signed overflow. (See issue 13496.) */ + printf("lo: %d\n", lo); + printf("hi: %d\n", hi); + printf("mid: %d\n", mid); + mid = ((size_t)lo + hi) / 2; litem = PySequence_GetItem(list, mid); if (litem == NULL) return -1; @@ -122,7 +128,10 @@ return -1; } while (lo < hi) { - mid = (lo + hi) / 2; + /* The (size_t)cast ensures that the addition and subsequent division + are performed as unsigned operations, avoiding difficulties from + signed overflow. (See issue 13496.) */ + mid = ((size_t)lo + hi) / 2; litem = PySequence_GetItem(list, mid); if (litem == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 17:45:35 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 15 Apr 2012 17:45:35 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Remove_accident?= =?utf8?q?ally-committed_debugging_code=2E?= Message-ID: http://hg.python.org/cpython/rev/bfe2d1acc09d changeset: 76326:bfe2d1acc09d branch: 2.7 user: Mark Dickinson date: Sun Apr 15 16:45:31 2012 +0100 summary: Remove accidentally-committed debugging code. files: Modules/_bisectmodule.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -24,9 +24,6 @@ /* The (size_t)cast ensures that the addition and subsequent division are performed as unsigned operations, avoiding difficulties from signed overflow. (See issue 13496.) */ - printf("lo: %d\n", lo); - printf("hi: %d\n", hi); - printf("mid: %d\n", mid); mid = ((size_t)lo + hi) / 2; litem = PySequence_GetItem(list, mid); if (litem == NULL) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 21:22:41 2012 From: python-checkins at python.org (philip.jenvey) Date: Sun, 15 Apr 2012 21:22:41 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_utilize_startswith=28tuple?= =?utf8?q?=29?= Message-ID: http://hg.python.org/cpython/rev/1ca10eb58483 changeset: 76327:1ca10eb58483 parent: 76324:1a9252280f07 user: Philip Jenvey date: Sun Apr 15 12:21:32 2012 -0700 summary: utilize startswith(tuple) files: Lib/importlib/_bootstrap.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -23,7 +23,7 @@ def _make_relax_case(): - if any(map(sys.platform.startswith, CASE_INSENSITIVE_PLATFORMS)): + if sys.platform.startswith(CASE_INSENSITIVE_PLATFORMS): def _relax_case(): """True if filenames must be checked case-insensitively.""" return b'PYTHONCASEOK' in _os.environ @@ -163,7 +163,7 @@ def verbose_message(message, *args): """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" if sys.flags.verbose: - if not message.startswith('#') and not message.startswith('import '): + if not message.startswith(('#', 'import ')): message = '# ' + message print(message.format(*args), file=sys.stderr) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 21:25:22 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 21:25:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Set_ImportError=2Ename_when?= =?utf8?q?_raising_the_exception_in_the_case_of_None?= Message-ID: http://hg.python.org/cpython/rev/c9fb9f5e16e7 changeset: 76328:c9fb9f5e16e7 parent: 76324:1a9252280f07 user: Brett Cannon date: Sun Apr 15 14:15:31 2012 -0400 summary: Set ImportError.name when raising the exception in the case of None found in sys.modules. files: Python/import.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2980,8 +2980,11 @@ mod = PyDict_GetItem(interp->modules, abs_name); if (mod == Py_None) { - PyErr_Format(PyExc_ImportError, - "import of %R halted; None in sys.modules", abs_name); + PyObject *msg = PyUnicode_FromFormat("import of %R halted; " + "None in sys.modules", abs_name); + if (msg != NULL) { + PyErr_SetFromImportErrorWithName(msg, abs_name); + } goto error_with_unlock; } else if (mod != NULL) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 21:25:22 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 21:25:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314582=3A_Import_re?= =?utf8?q?turns_the_module_returned_by_a_loader_instead?= Message-ID: http://hg.python.org/cpython/rev/005fd1fe31ab changeset: 76329:005fd1fe31ab user: Brett Cannon date: Sun Apr 15 15:24:04 2012 -0400 summary: Issue #14582: Import returns the module returned by a loader instead of sys.modules when possible. This is being done for two reasons. One is to gain a little bit of performance by skipping an unnecessary dict lookup in sys.modules. But the other (and main) reason is to be a little bit more clear in how things should work from the perspective of import's interactions with loaders. Otherwise loaders can easily forget to return the module even though PEP 302 explicitly states they are expected to return the module they loaded. files: Lib/importlib/_bootstrap.py | 16 +- Lib/importlib/test/import_/test_caching.py | 32 +- Misc/NEWS | 3 + Python/import.c | 19 +- Python/importlib.h | 924 +++++---- 5 files changed, 494 insertions(+), 500 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -974,12 +974,12 @@ loader = _find_module(name, path) if loader is None: raise ImportError(_ERR_MSG.format(name), name=name) - elif name not in sys.modules: - # The parent import may have already imported this module. - loader.load_module(name) + elif name in sys.modules: + # The parent module already imported this module. + module = sys.modules[name] + else: + module = loader.load_module(name) verbose_message('import {!r} # {!r}', name, loader) - # Backwards-compatibility; be nicer to skip the dict lookup. - module = sys.modules[name] if parent: # Set the module as an attribute on its parent. parent_module = sys.modules[parent] @@ -1078,7 +1078,11 @@ # Return up to the first dot in 'name'. This is complicated by the fact # that 'name' may be relative. if level == 0: - return sys.modules[name.partition('.')[0]] + index = name.find('.') + if index == -1: + return module + else: + return sys.modules[name[:index]] elif not name: return module else: diff --git a/Lib/importlib/test/import_/test_caching.py b/Lib/importlib/test/import_/test_caching.py --- a/Lib/importlib/test/import_/test_caching.py +++ b/Lib/importlib/test/import_/test_caching.py @@ -47,36 +47,12 @@ mock.load_module = MethodType(load_module, mock) return mock - # __import__ inconsistent between loaders and built-in import when it comes - # to when to use the module in sys.modules and when not to. - @import_util.importlib_only - def test_using_cache_after_loader(self): - # [from cache on return] - with self.create_mock('module') as mock: + def test_using_loader_return(self): + loader_return = 'hi there!' + with self.create_mock('module', return_=loader_return) as mock: with util.import_state(meta_path=[mock]): module = import_util.import_('module') - self.assertEqual(id(module), id(sys.modules['module'])) - - # See test_using_cache_after_loader() for reasoning. - @import_util.importlib_only - def test_using_cache_for_assigning_to_attribute(self): - # [from cache to attribute] - with self.create_mock('pkg.__init__', 'pkg.module') as importer: - with util.import_state(meta_path=[importer]): - module = import_util.import_('pkg.module') - self.assertTrue(hasattr(module, 'module')) - self.assertTrue(id(module.module), id(sys.modules['pkg.module'])) - - # See test_using_cache_after_loader() for reasoning. - @import_util.importlib_only - def test_using_cache_for_fromlist(self): - # [from cache for fromlist] - with self.create_mock('pkg.__init__', 'pkg.module') as importer: - with util.import_state(meta_path=[importer]): - module = import_util.import_('pkg', fromlist=['module']) - self.assertTrue(hasattr(module, 'module')) - self.assertEqual(id(module.module), - id(sys.modules['pkg.module'])) + self.assertEqual(module, loader_return) def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14582: Import directly returns the module as returned by a loader when + possible instead of fetching it from sys.modules. + - Issue #13889: Check and (if necessary) set FPU control word before calling any of the dtoa.c string <-> float conversion functions, on MSVC builds of Python. This fixes issues when embedding Python in a Delphi app. diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -3019,15 +3019,22 @@ Py_DECREF(partition); if (level == 0) { - final_mod = PyDict_GetItem(interp->modules, front); + if (PyUnicode_GET_LENGTH(name) == + PyUnicode_GET_LENGTH(front)) { + final_mod = mod; + } + else { + final_mod = PyDict_GetItem(interp->modules, front); + if (final_mod == NULL) { + PyErr_Format(PyExc_KeyError, + "%R not in sys.modules as expected", front); + } + } Py_DECREF(front); if (final_mod == NULL) { - PyErr_Format(PyExc_KeyError, - "%R not in sys.modules as expected", front); + goto error_with_unlock; } - else { - Py_INCREF(final_mod); - } + Py_INCREF(final_mod); } else { Py_ssize_t cut_off = PyUnicode_GetLength(name) - diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h @@ -2606,7 +2606,7 @@ 115,97,110,105,116,121,95,99,104,101,99,107,117,20,0,0, 0,78,111,32,109,111,100,117,108,101,32,110,97,109,101,100, 32,123,33,114,125,99,2,0,0,0,0,0,0,0,8,0, - 0,0,20,0,0,0,67,0,0,0,115,205,1,0,0,100, + 0,0,20,0,0,0,67,0,0,0,115,207,1,0,0,100, 9,0,125,2,0,124,0,0,106,1,0,100,1,0,131,1, 0,100,2,0,25,125,3,0,124,3,0,114,175,0,124,3, 0,116,2,0,106,3,0,107,7,0,114,59,0,124,1,0, @@ -2621,468 +2621,472 @@ 0,124,0,0,124,2,0,131,2,0,125,6,0,124,6,0, 100,9,0,107,8,0,114,232,0,116,8,0,116,6,0,106, 7,0,124,0,0,131,1,0,100,4,0,124,0,0,131,1, - 1,130,1,0,110,47,0,124,0,0,116,2,0,106,3,0, - 107,7,0,114,23,1,124,6,0,106,10,0,124,0,0,131, - 1,0,1,116,11,0,100,5,0,124,0,0,124,6,0,131, - 3,0,1,110,0,0,116,2,0,106,3,0,124,0,0,25, - 125,7,0,124,3,0,114,87,1,116,2,0,106,3,0,124, - 3,0,25,125,4,0,116,12,0,124,4,0,124,0,0,106, - 1,0,100,1,0,131,1,0,100,6,0,25,124,7,0,131, - 3,0,1,110,0,0,116,13,0,124,7,0,100,7,0,131, - 2,0,12,115,118,1,124,7,0,106,14,0,100,9,0,107, - 8,0,114,201,1,121,59,0,124,7,0,106,15,0,124,7, - 0,95,14,0,116,13,0,124,7,0,100,8,0,131,2,0, - 115,176,1,124,7,0,106,14,0,106,1,0,100,1,0,131, - 1,0,100,2,0,25,124,7,0,95,14,0,110,0,0,87, - 113,201,1,4,116,5,0,107,10,0,114,197,1,1,1,1, - 89,113,201,1,88,110,0,0,124,7,0,83,40,10,0,0, - 0,117,25,0,0,0,70,105,110,100,32,97,110,100,32,108, - 111,97,100,32,116,104,101,32,109,111,100,117,108,101,46,117, - 1,0,0,0,46,105,0,0,0,0,117,21,0,0,0,59, - 32,123,125,32,105,115,32,110,111,116,32,97,32,112,97,99, - 107,97,103,101,117,4,0,0,0,110,97,109,101,117,18,0, - 0,0,105,109,112,111,114,116,32,123,33,114,125,32,35,32, - 123,33,114,125,105,2,0,0,0,117,11,0,0,0,95,95, - 112,97,99,107,97,103,101,95,95,117,8,0,0,0,95,95, - 112,97,116,104,95,95,78,40,16,0,0,0,117,4,0,0, - 0,78,111,110,101,117,10,0,0,0,114,112,97,114,116,105, - 116,105,111,110,117,3,0,0,0,115,121,115,117,7,0,0, - 0,109,111,100,117,108,101,115,117,8,0,0,0,95,95,112, - 97,116,104,95,95,117,14,0,0,0,65,116,116,114,105,98, - 117,116,101,69,114,114,111,114,117,8,0,0,0,95,69,82, - 82,95,77,83,71,117,6,0,0,0,102,111,114,109,97,116, - 117,11,0,0,0,73,109,112,111,114,116,69,114,114,111,114, - 117,12,0,0,0,95,102,105,110,100,95,109,111,100,117,108, - 101,117,11,0,0,0,108,111,97,100,95,109,111,100,117,108, - 101,117,15,0,0,0,118,101,114,98,111,115,101,95,109,101, - 115,115,97,103,101,117,7,0,0,0,115,101,116,97,116,116, - 114,117,7,0,0,0,104,97,115,97,116,116,114,117,11,0, - 0,0,95,95,112,97,99,107,97,103,101,95,95,117,8,0, - 0,0,95,95,110,97,109,101,95,95,40,8,0,0,0,117, - 4,0,0,0,110,97,109,101,117,7,0,0,0,105,109,112, - 111,114,116,95,117,4,0,0,0,112,97,116,104,117,6,0, - 0,0,112,97,114,101,110,116,117,13,0,0,0,112,97,114, - 101,110,116,95,109,111,100,117,108,101,117,3,0,0,0,109, - 115,103,117,6,0,0,0,108,111,97,100,101,114,117,6,0, - 0,0,109,111,100,117,108,101,40,0,0,0,0,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,14,0,0,0,95,102,105,110,100,95,97, - 110,100,95,108,111,97,100,189,3,0,0,115,62,0,0,0, - 0,2,6,1,19,1,6,1,15,1,13,2,15,1,11,2, - 13,1,3,1,13,1,13,1,22,1,26,1,15,1,12,1, - 30,1,15,2,13,1,19,2,13,1,6,2,13,1,32,2, - 31,1,3,1,12,1,15,1,32,1,13,1,8,1,117,14, - 0,0,0,95,102,105,110,100,95,97,110,100,95,108,111,97, - 100,105,0,0,0,0,99,3,0,0,0,0,0,0,0,5, - 0,0,0,18,0,0,0,67,0,0,0,115,172,0,0,0, - 116,0,0,124,0,0,124,1,0,124,2,0,131,3,0,1, - 124,2,0,100,1,0,107,4,0,114,49,0,116,1,0,124, - 0,0,124,1,0,124,2,0,131,3,0,125,0,0,110,0, - 0,116,2,0,131,0,0,143,108,0,1,121,69,0,116,3, - 0,106,4,0,124,0,0,25,125,3,0,124,3,0,100,4, - 0,107,8,0,114,123,0,100,2,0,106,6,0,124,0,0, - 131,1,0,125,4,0,116,7,0,124,4,0,100,3,0,124, - 0,0,131,1,1,130,1,0,110,0,0,124,3,0,83,87, - 110,18,0,4,116,8,0,107,10,0,114,148,0,1,1,1, - 89,110,1,0,88,116,9,0,124,0,0,116,10,0,131,2, - 0,83,87,100,4,0,81,88,100,4,0,83,40,5,0,0, - 0,117,50,1,0,0,73,109,112,111,114,116,32,97,110,100, - 32,114,101,116,117,114,110,32,116,104,101,32,109,111,100,117, - 108,101,32,98,97,115,101,100,32,111,110,32,105,116,115,32, - 110,97,109,101,44,32,116,104,101,32,112,97,99,107,97,103, - 101,32,116,104,101,32,99,97,108,108,32,105,115,10,32,32, - 32,32,98,101,105,110,103,32,109,97,100,101,32,102,114,111, - 109,44,32,97,110,100,32,116,104,101,32,108,101,118,101,108, - 32,97,100,106,117,115,116,109,101,110,116,46,10,10,32,32, - 32,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32, - 114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,103, - 114,101,97,116,101,115,116,32,99,111,109,109,111,110,32,100, - 101,110,111,109,105,110,97,116,111,114,32,111,102,32,102,117, - 110,99,116,105,111,110,97,108,105,116,121,10,32,32,32,32, - 98,101,116,119,101,101,110,32,105,109,112,111,114,116,95,109, - 111,100,117,108,101,32,97,110,100,32,95,95,105,109,112,111, - 114,116,95,95,46,32,84,104,105,115,32,105,110,99,108,117, - 100,101,115,32,115,101,116,116,105,110,103,32,95,95,112,97, - 99,107,97,103,101,95,95,32,105,102,10,32,32,32,32,116, - 104,101,32,108,111,97,100,101,114,32,100,105,100,32,110,111, - 116,46,10,10,32,32,32,32,105,0,0,0,0,117,40,0, - 0,0,105,109,112,111,114,116,32,111,102,32,123,125,32,104, - 97,108,116,101,100,59,32,78,111,110,101,32,105,110,32,115, - 121,115,46,109,111,100,117,108,101,115,117,4,0,0,0,110, - 97,109,101,78,40,11,0,0,0,117,13,0,0,0,95,115, - 97,110,105,116,121,95,99,104,101,99,107,117,13,0,0,0, - 95,114,101,115,111,108,118,101,95,110,97,109,101,117,18,0, - 0,0,95,73,109,112,111,114,116,76,111,99,107,67,111,110, - 116,101,120,116,117,3,0,0,0,115,121,115,117,7,0,0, - 0,109,111,100,117,108,101,115,117,4,0,0,0,78,111,110, - 101,117,6,0,0,0,102,111,114,109,97,116,117,11,0,0, - 0,73,109,112,111,114,116,69,114,114,111,114,117,8,0,0, - 0,75,101,121,69,114,114,111,114,117,14,0,0,0,95,102, - 105,110,100,95,97,110,100,95,108,111,97,100,117,11,0,0, - 0,95,103,99,100,95,105,109,112,111,114,116,40,5,0,0, - 0,117,4,0,0,0,110,97,109,101,117,7,0,0,0,112, - 97,99,107,97,103,101,117,5,0,0,0,108,101,118,101,108, - 117,6,0,0,0,109,111,100,117,108,101,117,7,0,0,0, - 109,101,115,115,97,103,101,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 1,130,1,0,110,62,0,124,0,0,116,2,0,106,3,0, + 107,6,0,114,7,1,116,2,0,106,3,0,124,0,0,25, + 125,7,0,110,31,0,124,6,0,106,10,0,124,0,0,131, + 1,0,125,7,0,116,11,0,100,5,0,124,0,0,124,6, + 0,131,3,0,1,124,3,0,114,89,1,116,2,0,106,3, + 0,124,3,0,25,125,4,0,116,12,0,124,4,0,124,0, + 0,106,1,0,100,1,0,131,1,0,100,6,0,25,124,7, + 0,131,3,0,1,110,0,0,116,13,0,124,7,0,100,7, + 0,131,2,0,12,115,120,1,124,7,0,106,14,0,100,9, + 0,107,8,0,114,203,1,121,59,0,124,7,0,106,15,0, + 124,7,0,95,14,0,116,13,0,124,7,0,100,8,0,131, + 2,0,115,178,1,124,7,0,106,14,0,106,1,0,100,1, + 0,131,1,0,100,2,0,25,124,7,0,95,14,0,110,0, + 0,87,113,203,1,4,116,5,0,107,10,0,114,199,1,1, + 1,1,89,113,203,1,88,110,0,0,124,7,0,83,40,10, + 0,0,0,117,25,0,0,0,70,105,110,100,32,97,110,100, + 32,108,111,97,100,32,116,104,101,32,109,111,100,117,108,101, + 46,117,1,0,0,0,46,105,0,0,0,0,117,21,0,0, + 0,59,32,123,125,32,105,115,32,110,111,116,32,97,32,112, + 97,99,107,97,103,101,117,4,0,0,0,110,97,109,101,117, + 18,0,0,0,105,109,112,111,114,116,32,123,33,114,125,32, + 35,32,123,33,114,125,105,2,0,0,0,117,11,0,0,0, + 95,95,112,97,99,107,97,103,101,95,95,117,8,0,0,0, + 95,95,112,97,116,104,95,95,78,40,16,0,0,0,117,4, + 0,0,0,78,111,110,101,117,10,0,0,0,114,112,97,114, + 116,105,116,105,111,110,117,3,0,0,0,115,121,115,117,7, + 0,0,0,109,111,100,117,108,101,115,117,8,0,0,0,95, + 95,112,97,116,104,95,95,117,14,0,0,0,65,116,116,114, + 105,98,117,116,101,69,114,114,111,114,117,8,0,0,0,95, + 69,82,82,95,77,83,71,117,6,0,0,0,102,111,114,109, + 97,116,117,11,0,0,0,73,109,112,111,114,116,69,114,114, + 111,114,117,12,0,0,0,95,102,105,110,100,95,109,111,100, + 117,108,101,117,11,0,0,0,108,111,97,100,95,109,111,100, + 117,108,101,117,15,0,0,0,118,101,114,98,111,115,101,95, + 109,101,115,115,97,103,101,117,7,0,0,0,115,101,116,97, + 116,116,114,117,7,0,0,0,104,97,115,97,116,116,114,117, + 11,0,0,0,95,95,112,97,99,107,97,103,101,95,95,117, + 8,0,0,0,95,95,110,97,109,101,95,95,40,8,0,0, + 0,117,4,0,0,0,110,97,109,101,117,7,0,0,0,105, + 109,112,111,114,116,95,117,4,0,0,0,112,97,116,104,117, + 6,0,0,0,112,97,114,101,110,116,117,13,0,0,0,112, + 97,114,101,110,116,95,109,111,100,117,108,101,117,3,0,0, + 0,109,115,103,117,6,0,0,0,108,111,97,100,101,114,117, + 6,0,0,0,109,111,100,117,108,101,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,14,0,0,0,95,102,105,110,100, + 95,97,110,100,95,108,111,97,100,189,3,0,0,115,62,0, + 0,0,0,2,6,1,19,1,6,1,15,1,13,2,15,1, + 11,2,13,1,3,1,13,1,13,1,22,1,26,1,15,1, + 12,1,30,1,15,2,16,2,15,1,16,1,6,2,13,1, + 32,2,31,1,3,1,12,1,15,1,32,1,13,1,8,1, + 117,14,0,0,0,95,102,105,110,100,95,97,110,100,95,108, + 111,97,100,105,0,0,0,0,99,3,0,0,0,0,0,0, + 0,5,0,0,0,18,0,0,0,67,0,0,0,115,172,0, + 0,0,116,0,0,124,0,0,124,1,0,124,2,0,131,3, + 0,1,124,2,0,100,1,0,107,4,0,114,49,0,116,1, + 0,124,0,0,124,1,0,124,2,0,131,3,0,125,0,0, + 110,0,0,116,2,0,131,0,0,143,108,0,1,121,69,0, + 116,3,0,106,4,0,124,0,0,25,125,3,0,124,3,0, + 100,4,0,107,8,0,114,123,0,100,2,0,106,6,0,124, + 0,0,131,1,0,125,4,0,116,7,0,124,4,0,100,3, + 0,124,0,0,131,1,1,130,1,0,110,0,0,124,3,0, + 83,87,110,18,0,4,116,8,0,107,10,0,114,148,0,1, + 1,1,89,110,1,0,88,116,9,0,124,0,0,116,10,0, + 131,2,0,83,87,100,4,0,81,88,100,4,0,83,40,5, + 0,0,0,117,50,1,0,0,73,109,112,111,114,116,32,97, + 110,100,32,114,101,116,117,114,110,32,116,104,101,32,109,111, + 100,117,108,101,32,98,97,115,101,100,32,111,110,32,105,116, + 115,32,110,97,109,101,44,32,116,104,101,32,112,97,99,107, + 97,103,101,32,116,104,101,32,99,97,108,108,32,105,115,10, + 32,32,32,32,98,101,105,110,103,32,109,97,100,101,32,102, + 114,111,109,44,32,97,110,100,32,116,104,101,32,108,101,118, + 101,108,32,97,100,106,117,115,116,109,101,110,116,46,10,10, + 32,32,32,32,84,104,105,115,32,102,117,110,99,116,105,111, + 110,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101, + 32,103,114,101,97,116,101,115,116,32,99,111,109,109,111,110, + 32,100,101,110,111,109,105,110,97,116,111,114,32,111,102,32, + 102,117,110,99,116,105,111,110,97,108,105,116,121,10,32,32, + 32,32,98,101,116,119,101,101,110,32,105,109,112,111,114,116, + 95,109,111,100,117,108,101,32,97,110,100,32,95,95,105,109, + 112,111,114,116,95,95,46,32,84,104,105,115,32,105,110,99, + 108,117,100,101,115,32,115,101,116,116,105,110,103,32,95,95, + 112,97,99,107,97,103,101,95,95,32,105,102,10,32,32,32, + 32,116,104,101,32,108,111,97,100,101,114,32,100,105,100,32, + 110,111,116,46,10,10,32,32,32,32,105,0,0,0,0,117, + 40,0,0,0,105,109,112,111,114,116,32,111,102,32,123,125, + 32,104,97,108,116,101,100,59,32,78,111,110,101,32,105,110, + 32,115,121,115,46,109,111,100,117,108,101,115,117,4,0,0, + 0,110,97,109,101,78,40,11,0,0,0,117,13,0,0,0, + 95,115,97,110,105,116,121,95,99,104,101,99,107,117,13,0, + 0,0,95,114,101,115,111,108,118,101,95,110,97,109,101,117, + 18,0,0,0,95,73,109,112,111,114,116,76,111,99,107,67, + 111,110,116,101,120,116,117,3,0,0,0,115,121,115,117,7, + 0,0,0,109,111,100,117,108,101,115,117,4,0,0,0,78, + 111,110,101,117,6,0,0,0,102,111,114,109,97,116,117,11, + 0,0,0,73,109,112,111,114,116,69,114,114,111,114,117,8, + 0,0,0,75,101,121,69,114,114,111,114,117,14,0,0,0, + 95,102,105,110,100,95,97,110,100,95,108,111,97,100,117,11, + 0,0,0,95,103,99,100,95,105,109,112,111,114,116,40,5, + 0,0,0,117,4,0,0,0,110,97,109,101,117,7,0,0, + 0,112,97,99,107,97,103,101,117,5,0,0,0,108,101,118, + 101,108,117,6,0,0,0,109,111,100,117,108,101,117,7,0, + 0,0,109,101,115,115,97,103,101,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,11,0,0,0,95,103,99,100,95,105, + 109,112,111,114,116,230,3,0,0,115,28,0,0,0,0,9, + 16,1,12,1,21,1,10,1,3,1,13,1,12,1,6,1, + 9,1,21,1,8,1,13,1,5,1,117,11,0,0,0,95, + 103,99,100,95,105,109,112,111,114,116,99,3,0,0,0,0, + 0,0,0,4,0,0,0,13,0,0,0,3,0,0,0,115, + 179,0,0,0,116,0,0,136,0,0,100,1,0,131,2,0, + 114,175,0,100,2,0,124,1,0,107,6,0,114,86,0,116, + 0,0,136,0,0,100,3,0,131,2,0,114,86,0,116,1, + 0,124,1,0,131,1,0,125,1,0,124,1,0,106,2,0, + 100,2,0,131,1,0,1,124,1,0,106,3,0,136,0,0, + 106,4,0,131,1,0,1,110,0,0,120,86,0,135,0,0, + 102,1,0,100,4,0,100,5,0,134,0,0,124,1,0,68, + 131,1,0,68,93,56,0,125,3,0,121,29,0,124,2,0, + 100,6,0,106,5,0,136,0,0,106,6,0,124,3,0,131, + 2,0,131,1,0,1,87,113,112,0,4,116,7,0,107,10, + 0,114,167,0,1,1,1,89,113,112,0,88,113,112,0,87, + 110,0,0,136,0,0,83,40,7,0,0,0,117,238,0,0, + 0,70,105,103,117,114,101,32,111,117,116,32,119,104,97,116, + 32,95,95,105,109,112,111,114,116,95,95,32,115,104,111,117, + 108,100,32,114,101,116,117,114,110,46,10,10,32,32,32,32, + 84,104,101,32,105,109,112,111,114,116,95,32,112,97,114,97, + 109,101,116,101,114,32,105,115,32,97,32,99,97,108,108,97, + 98,108,101,32,119,104,105,99,104,32,116,97,107,101,115,32, + 116,104,101,32,110,97,109,101,32,111,102,32,109,111,100,117, + 108,101,32,116,111,10,32,32,32,32,105,109,112,111,114,116, + 46,32,73,116,32,105,115,32,114,101,113,117,105,114,101,100, + 32,116,111,32,100,101,99,111,117,112,108,101,32,116,104,101, + 32,102,117,110,99,116,105,111,110,32,102,114,111,109,32,97, + 115,115,117,109,105,110,103,32,105,109,112,111,114,116,108,105, + 98,39,115,10,32,32,32,32,105,109,112,111,114,116,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,105,115, + 32,100,101,115,105,114,101,100,46,10,10,32,32,32,32,117, + 8,0,0,0,95,95,112,97,116,104,95,95,117,1,0,0, + 0,42,117,7,0,0,0,95,95,97,108,108,95,95,99,1, + 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,51, + 0,0,0,115,36,0,0,0,124,0,0,93,26,0,125,1, + 0,116,0,0,136,0,0,124,1,0,131,2,0,115,3,0, + 124,1,0,86,1,113,3,0,100,0,0,83,40,1,0,0, + 0,78,40,1,0,0,0,117,7,0,0,0,104,97,115,97, + 116,116,114,40,2,0,0,0,117,2,0,0,0,46,48,117, + 1,0,0,0,121,40,1,0,0,0,117,6,0,0,0,109, + 111,100,117,108,101,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,9,0,0, + 0,60,103,101,110,101,120,112,114,62,14,4,0,0,115,2, + 0,0,0,6,0,117,35,0,0,0,95,104,97,110,100,108, + 101,95,102,114,111,109,108,105,115,116,46,60,108,111,99,97, + 108,115,62,46,60,103,101,110,101,120,112,114,62,117,7,0, + 0,0,123,48,125,46,123,49,125,40,8,0,0,0,117,7, + 0,0,0,104,97,115,97,116,116,114,117,4,0,0,0,108, + 105,115,116,117,6,0,0,0,114,101,109,111,118,101,117,6, + 0,0,0,101,120,116,101,110,100,117,7,0,0,0,95,95, + 97,108,108,95,95,117,6,0,0,0,102,111,114,109,97,116, + 117,8,0,0,0,95,95,110,97,109,101,95,95,117,11,0, + 0,0,73,109,112,111,114,116,69,114,114,111,114,40,4,0, + 0,0,117,6,0,0,0,109,111,100,117,108,101,117,8,0, + 0,0,102,114,111,109,108,105,115,116,117,7,0,0,0,105, + 109,112,111,114,116,95,117,1,0,0,0,120,40,0,0,0, + 0,40,1,0,0,0,117,6,0,0,0,109,111,100,117,108, + 101,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,11,0,0,0,95,103,99,100,95,105,109,112, - 111,114,116,230,3,0,0,115,28,0,0,0,0,9,16,1, - 12,1,21,1,10,1,3,1,13,1,12,1,6,1,9,1, - 21,1,8,1,13,1,5,1,117,11,0,0,0,95,103,99, - 100,95,105,109,112,111,114,116,99,3,0,0,0,0,0,0, - 0,4,0,0,0,13,0,0,0,3,0,0,0,115,179,0, - 0,0,116,0,0,136,0,0,100,1,0,131,2,0,114,175, - 0,100,2,0,124,1,0,107,6,0,114,86,0,116,0,0, - 136,0,0,100,3,0,131,2,0,114,86,0,116,1,0,124, - 1,0,131,1,0,125,1,0,124,1,0,106,2,0,100,2, - 0,131,1,0,1,124,1,0,106,3,0,136,0,0,106,4, - 0,131,1,0,1,110,0,0,120,86,0,135,0,0,102,1, - 0,100,4,0,100,5,0,134,0,0,124,1,0,68,131,1, - 0,68,93,56,0,125,3,0,121,29,0,124,2,0,100,6, - 0,106,5,0,136,0,0,106,6,0,124,3,0,131,2,0, - 131,1,0,1,87,113,112,0,4,116,7,0,107,10,0,114, - 167,0,1,1,1,89,113,112,0,88,113,112,0,87,110,0, - 0,136,0,0,83,40,7,0,0,0,117,238,0,0,0,70, - 105,103,117,114,101,32,111,117,116,32,119,104,97,116,32,95, - 95,105,109,112,111,114,116,95,95,32,115,104,111,117,108,100, - 32,114,101,116,117,114,110,46,10,10,32,32,32,32,84,104, - 101,32,105,109,112,111,114,116,95,32,112,97,114,97,109,101, - 116,101,114,32,105,115,32,97,32,99,97,108,108,97,98,108, - 101,32,119,104,105,99,104,32,116,97,107,101,115,32,116,104, - 101,32,110,97,109,101,32,111,102,32,109,111,100,117,108,101, - 32,116,111,10,32,32,32,32,105,109,112,111,114,116,46,32, - 73,116,32,105,115,32,114,101,113,117,105,114,101,100,32,116, - 111,32,100,101,99,111,117,112,108,101,32,116,104,101,32,102, - 117,110,99,116,105,111,110,32,102,114,111,109,32,97,115,115, - 117,109,105,110,103,32,105,109,112,111,114,116,108,105,98,39, - 115,10,32,32,32,32,105,109,112,111,114,116,32,105,109,112, - 108,101,109,101,110,116,97,116,105,111,110,32,105,115,32,100, - 101,115,105,114,101,100,46,10,10,32,32,32,32,117,8,0, - 0,0,95,95,112,97,116,104,95,95,117,1,0,0,0,42, - 117,7,0,0,0,95,95,97,108,108,95,95,99,1,0,0, - 0,0,0,0,0,2,0,0,0,4,0,0,0,51,0,0, - 0,115,36,0,0,0,124,0,0,93,26,0,125,1,0,116, - 0,0,136,0,0,124,1,0,131,2,0,115,3,0,124,1, - 0,86,1,113,3,0,100,0,0,83,40,1,0,0,0,78, - 40,1,0,0,0,117,7,0,0,0,104,97,115,97,116,116, - 114,40,2,0,0,0,117,2,0,0,0,46,48,117,1,0, - 0,0,121,40,1,0,0,0,117,6,0,0,0,109,111,100, - 117,108,101,40,0,0,0,0,117,29,0,0,0,60,102,114, + 97,112,62,117,16,0,0,0,95,104,97,110,100,108,101,95, + 102,114,111,109,108,105,115,116,255,3,0,0,115,22,0,0, + 0,0,10,15,1,27,1,12,1,13,1,19,1,32,1,3, + 1,29,1,13,1,12,1,117,16,0,0,0,95,104,97,110, + 100,108,101,95,102,114,111,109,108,105,115,116,99,1,0,0, + 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, + 0,115,78,0,0,0,124,0,0,106,0,0,100,1,0,131, + 1,0,125,1,0,124,1,0,100,6,0,107,8,0,114,74, + 0,124,0,0,100,2,0,25,125,1,0,100,3,0,124,0, + 0,107,7,0,114,74,0,124,1,0,106,2,0,100,4,0, + 131,1,0,100,5,0,25,125,1,0,113,74,0,110,0,0, + 124,1,0,83,40,7,0,0,0,117,167,0,0,0,67,97, + 108,99,117,108,97,116,101,32,119,104,97,116,32,95,95,112, + 97,99,107,97,103,101,95,95,32,115,104,111,117,108,100,32, + 98,101,46,10,10,32,32,32,32,95,95,112,97,99,107,97, + 103,101,95,95,32,105,115,32,110,111,116,32,103,117,97,114, + 97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,102, + 105,110,101,100,32,111,114,32,99,111,117,108,100,32,98,101, + 32,115,101,116,32,116,111,32,78,111,110,101,10,32,32,32, + 32,116,111,32,114,101,112,114,101,115,101,110,116,32,116,104, + 97,116,32,105,116,115,32,112,114,111,112,101,114,32,118,97, + 108,117,101,32,105,115,32,117,110,107,110,111,119,110,46,10, + 10,32,32,32,32,117,11,0,0,0,95,95,112,97,99,107, + 97,103,101,95,95,117,8,0,0,0,95,95,110,97,109,101, + 95,95,117,8,0,0,0,95,95,112,97,116,104,95,95,117, + 1,0,0,0,46,105,0,0,0,0,78,40,3,0,0,0, + 117,3,0,0,0,103,101,116,117,4,0,0,0,78,111,110, + 101,117,10,0,0,0,114,112,97,114,116,105,116,105,111,110, + 40,2,0,0,0,117,7,0,0,0,103,108,111,98,97,108, + 115,117,7,0,0,0,112,97,99,107,97,103,101,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,17,0,0,0,95,99, + 97,108,99,95,95,95,112,97,99,107,97,103,101,95,95,22, + 4,0,0,115,12,0,0,0,0,7,15,1,12,1,10,1, + 12,1,25,1,117,17,0,0,0,95,99,97,108,99,95,95, + 95,112,97,99,107,97,103,101,95,95,99,5,0,0,0,0, + 0,0,0,9,0,0,0,5,0,0,0,67,0,0,0,115, + 235,0,0,0,124,4,0,100,1,0,107,2,0,114,27,0, + 116,0,0,124,0,0,131,1,0,125,5,0,110,30,0,116, + 1,0,124,1,0,131,1,0,125,6,0,116,0,0,124,0, + 0,124,6,0,124,4,0,131,3,0,125,5,0,124,3,0, + 115,215,0,124,4,0,100,1,0,107,2,0,114,130,0,124, + 0,0,106,2,0,100,2,0,131,1,0,125,7,0,124,7, + 0,100,5,0,107,2,0,114,106,0,124,5,0,83,116,3, + 0,106,4,0,124,0,0,100,4,0,124,7,0,133,2,0, + 25,25,83,113,231,0,124,0,0,115,140,0,124,5,0,83, + 116,5,0,124,0,0,131,1,0,116,5,0,124,0,0,106, + 6,0,100,2,0,131,1,0,100,1,0,25,131,1,0,24, + 125,8,0,116,3,0,106,4,0,124,5,0,106,7,0,100, + 4,0,116,5,0,124,5,0,106,7,0,131,1,0,124,8, + 0,24,133,2,0,25,25,83,110,16,0,116,8,0,124,5, + 0,124,3,0,116,0,0,131,3,0,83,100,4,0,83,40, + 6,0,0,0,117,214,1,0,0,73,109,112,111,114,116,32, + 97,32,109,111,100,117,108,101,46,10,10,32,32,32,32,84, + 104,101,32,39,103,108,111,98,97,108,115,39,32,97,114,103, + 117,109,101,110,116,32,105,115,32,117,115,101,100,32,116,111, + 32,105,110,102,101,114,32,119,104,101,114,101,32,116,104,101, + 32,105,109,112,111,114,116,32,105,115,32,111,99,99,117,114, + 105,110,103,32,102,114,111,109,10,32,32,32,32,116,111,32, + 104,97,110,100,108,101,32,114,101,108,97,116,105,118,101,32, + 105,109,112,111,114,116,115,46,32,84,104,101,32,39,108,111, + 99,97,108,115,39,32,97,114,103,117,109,101,110,116,32,105, + 115,32,105,103,110,111,114,101,100,46,32,84,104,101,10,32, + 32,32,32,39,102,114,111,109,108,105,115,116,39,32,97,114, + 103,117,109,101,110,116,32,115,112,101,99,105,102,105,101,115, + 32,119,104,97,116,32,115,104,111,117,108,100,32,101,120,105, + 115,116,32,97,115,32,97,116,116,114,105,98,117,116,101,115, + 32,111,110,32,116,104,101,32,109,111,100,117,108,101,10,32, + 32,32,32,98,101,105,110,103,32,105,109,112,111,114,116,101, + 100,32,40,101,46,103,46,32,96,96,102,114,111,109,32,109, + 111,100,117,108,101,32,105,109,112,111,114,116,32,60,102,114, + 111,109,108,105,115,116,62,96,96,41,46,32,32,84,104,101, + 32,39,108,101,118,101,108,39,10,32,32,32,32,97,114,103, + 117,109,101,110,116,32,114,101,112,114,101,115,101,110,116,115, + 32,116,104,101,32,112,97,99,107,97,103,101,32,108,111,99, + 97,116,105,111,110,32,116,111,32,105,109,112,111,114,116,32, + 102,114,111,109,32,105,110,32,97,32,114,101,108,97,116,105, + 118,101,10,32,32,32,32,105,109,112,111,114,116,32,40,101, + 46,103,46,32,96,96,102,114,111,109,32,46,46,112,107,103, + 32,105,109,112,111,114,116,32,109,111,100,96,96,32,119,111, + 117,108,100,32,104,97,118,101,32,97,32,39,108,101,118,101, + 108,39,32,111,102,32,50,41,46,10,10,32,32,32,32,105, + 0,0,0,0,117,1,0,0,0,46,105,1,0,0,0,78, + 105,255,255,255,255,40,9,0,0,0,117,11,0,0,0,95, + 103,99,100,95,105,109,112,111,114,116,117,17,0,0,0,95, + 99,97,108,99,95,95,95,112,97,99,107,97,103,101,95,95, + 117,4,0,0,0,102,105,110,100,117,3,0,0,0,115,121, + 115,117,7,0,0,0,109,111,100,117,108,101,115,117,3,0, + 0,0,108,101,110,117,9,0,0,0,112,97,114,116,105,116, + 105,111,110,117,8,0,0,0,95,95,110,97,109,101,95,95, + 117,16,0,0,0,95,104,97,110,100,108,101,95,102,114,111, + 109,108,105,115,116,40,9,0,0,0,117,4,0,0,0,110, + 97,109,101,117,7,0,0,0,103,108,111,98,97,108,115,117, + 6,0,0,0,108,111,99,97,108,115,117,8,0,0,0,102, + 114,111,109,108,105,115,116,117,5,0,0,0,108,101,118,101, + 108,117,6,0,0,0,109,111,100,117,108,101,117,7,0,0, + 0,112,97,99,107,97,103,101,117,5,0,0,0,105,110,100, + 101,120,117,7,0,0,0,99,117,116,95,111,102,102,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,9,0,0,0,60, - 103,101,110,101,120,112,114,62,14,4,0,0,115,2,0,0, - 0,6,0,117,35,0,0,0,95,104,97,110,100,108,101,95, - 102,114,111,109,108,105,115,116,46,60,108,111,99,97,108,115, - 62,46,60,103,101,110,101,120,112,114,62,117,7,0,0,0, - 123,48,125,46,123,49,125,40,8,0,0,0,117,7,0,0, - 0,104,97,115,97,116,116,114,117,4,0,0,0,108,105,115, - 116,117,6,0,0,0,114,101,109,111,118,101,117,6,0,0, - 0,101,120,116,101,110,100,117,7,0,0,0,95,95,97,108, - 108,95,95,117,6,0,0,0,102,111,114,109,97,116,117,8, - 0,0,0,95,95,110,97,109,101,95,95,117,11,0,0,0, - 73,109,112,111,114,116,69,114,114,111,114,40,4,0,0,0, - 117,6,0,0,0,109,111,100,117,108,101,117,8,0,0,0, - 102,114,111,109,108,105,115,116,117,7,0,0,0,105,109,112, - 111,114,116,95,117,1,0,0,0,120,40,0,0,0,0,40, - 1,0,0,0,117,6,0,0,0,109,111,100,117,108,101,117, + 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,95, + 95,105,109,112,111,114,116,95,95,37,4,0,0,115,30,0, + 0,0,0,11,12,1,15,2,12,1,18,1,6,3,12,1, + 15,1,12,1,4,2,24,1,6,1,4,2,35,1,40,2, + 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,99, + 2,0,0,0,0,0,0,0,9,0,0,0,12,0,0,0, + 67,0,0,0,115,109,1,0,0,124,1,0,97,0,0,124, + 0,0,97,1,0,120,47,0,116,0,0,116,1,0,102,2, + 0,68,93,33,0,125,2,0,116,2,0,124,2,0,100,1, + 0,131,2,0,115,25,0,116,3,0,124,2,0,95,4,0, + 113,25,0,113,25,0,87,116,1,0,106,5,0,116,6,0, + 25,125,3,0,120,76,0,100,17,0,68,93,68,0,125,4, + 0,124,4,0,116,1,0,106,5,0,107,7,0,114,121,0, + 116,3,0,106,7,0,124,4,0,131,1,0,125,5,0,110, + 13,0,116,1,0,106,5,0,124,4,0,25,125,5,0,116, + 8,0,124,3,0,124,4,0,124,5,0,131,3,0,1,113, + 82,0,87,120,153,0,100,18,0,100,19,0,100,20,0,103, + 3,0,68,93,124,0,92,2,0,125,6,0,125,7,0,124, + 6,0,116,1,0,106,5,0,107,6,0,114,214,0,116,1, + 0,106,5,0,124,6,0,25,125,8,0,80,113,170,0,121, + 56,0,116,3,0,106,7,0,124,6,0,131,1,0,125,8, + 0,124,6,0,100,10,0,107,2,0,114,12,1,100,11,0, + 116,1,0,106,9,0,107,6,0,114,12,1,100,7,0,125, + 7,0,110,0,0,80,87,113,170,0,4,116,10,0,107,10, + 0,114,37,1,1,1,1,119,170,0,89,113,170,0,88,113, + 170,0,87,116,10,0,100,12,0,131,1,0,130,1,0,116, + 8,0,124,3,0,100,13,0,124,8,0,131,3,0,1,116, + 8,0,124,3,0,100,14,0,124,7,0,131,3,0,1,116, + 8,0,124,3,0,100,15,0,116,11,0,131,0,0,131,3, + 0,1,100,16,0,83,40,21,0,0,0,117,249,0,0,0, + 83,101,116,117,112,32,105,109,112,111,114,116,108,105,98,32, + 98,121,32,105,109,112,111,114,116,105,110,103,32,110,101,101, + 100,101,100,32,98,117,105,108,116,45,105,110,32,109,111,100, + 117,108,101,115,32,97,110,100,32,105,110,106,101,99,116,105, + 110,103,32,116,104,101,109,10,32,32,32,32,105,110,116,111, + 32,116,104,101,32,103,108,111,98,97,108,32,110,97,109,101, + 115,112,97,99,101,46,10,10,32,32,32,32,65,115,32,115, + 121,115,32,105,115,32,110,101,101,100,101,100,32,102,111,114, + 32,115,121,115,46,109,111,100,117,108,101,115,32,97,99,99, + 101,115,115,32,97,110,100,32,105,109,112,32,105,115,32,110, + 101,101,100,101,100,32,116,111,32,108,111,97,100,32,98,117, + 105,108,116,45,105,110,10,32,32,32,32,109,111,100,117,108, + 101,115,44,32,116,104,111,115,101,32,116,119,111,32,109,111, + 100,117,108,101,115,32,109,117,115,116,32,98,101,32,101,120, + 112,108,105,99,105,116,108,121,32,112,97,115,115,101,100,32, + 105,110,46,10,10,32,32,32,32,117,10,0,0,0,95,95, + 108,111,97,100,101,114,95,95,117,3,0,0,0,95,105,111, + 117,9,0,0,0,95,119,97,114,110,105,110,103,115,117,8, + 0,0,0,98,117,105,108,116,105,110,115,117,7,0,0,0, + 109,97,114,115,104,97,108,117,5,0,0,0,112,111,115,105, + 120,117,1,0,0,0,47,117,2,0,0,0,110,116,117,1, + 0,0,0,92,117,3,0,0,0,111,115,50,117,7,0,0, + 0,69,77,88,32,71,67,67,117,30,0,0,0,105,109,112, + 111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,32, + 112,111,115,105,120,32,111,114,32,110,116,117,3,0,0,0, + 95,111,115,117,8,0,0,0,112,97,116,104,95,115,101,112, + 117,11,0,0,0,95,114,101,108,97,120,95,99,97,115,101, + 78,40,4,0,0,0,117,3,0,0,0,95,105,111,117,9, + 0,0,0,95,119,97,114,110,105,110,103,115,117,8,0,0, + 0,98,117,105,108,116,105,110,115,117,7,0,0,0,109,97, + 114,115,104,97,108,40,2,0,0,0,117,5,0,0,0,112, + 111,115,105,120,117,1,0,0,0,47,40,2,0,0,0,117, + 2,0,0,0,110,116,117,1,0,0,0,92,40,2,0,0, + 0,117,3,0,0,0,111,115,50,117,1,0,0,0,92,40, + 12,0,0,0,117,3,0,0,0,105,109,112,117,3,0,0, + 0,115,121,115,117,7,0,0,0,104,97,115,97,116,116,114, + 117,15,0,0,0,66,117,105,108,116,105,110,73,109,112,111, + 114,116,101,114,117,10,0,0,0,95,95,108,111,97,100,101, + 114,95,95,117,7,0,0,0,109,111,100,117,108,101,115,117, + 8,0,0,0,95,95,110,97,109,101,95,95,117,11,0,0, + 0,108,111,97,100,95,109,111,100,117,108,101,117,7,0,0, + 0,115,101,116,97,116,116,114,117,7,0,0,0,118,101,114, + 115,105,111,110,117,11,0,0,0,73,109,112,111,114,116,69, + 114,114,111,114,117,16,0,0,0,95,109,97,107,101,95,114, + 101,108,97,120,95,99,97,115,101,40,9,0,0,0,117,10, + 0,0,0,115,121,115,95,109,111,100,117,108,101,117,10,0, + 0,0,105,109,112,95,109,111,100,117,108,101,117,6,0,0, + 0,109,111,100,117,108,101,117,11,0,0,0,115,101,108,102, + 95,109,111,100,117,108,101,117,12,0,0,0,98,117,105,108, + 116,105,110,95,110,97,109,101,117,14,0,0,0,98,117,105, + 108,116,105,110,95,109,111,100,117,108,101,117,10,0,0,0, + 98,117,105,108,116,105,110,95,111,115,117,8,0,0,0,112, + 97,116,104,95,115,101,112,117,9,0,0,0,111,115,95,109, + 111,100,117,108,101,40,0,0,0,0,40,0,0,0,0,117, 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,16,0,0,0,95,104,97,110,100,108,101,95,102,114, - 111,109,108,105,115,116,255,3,0,0,115,22,0,0,0,0, - 10,15,1,27,1,12,1,13,1,19,1,32,1,3,1,29, - 1,13,1,12,1,117,16,0,0,0,95,104,97,110,100,108, - 101,95,102,114,111,109,108,105,115,116,99,1,0,0,0,0, - 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, - 78,0,0,0,124,0,0,106,0,0,100,1,0,131,1,0, - 125,1,0,124,1,0,100,6,0,107,8,0,114,74,0,124, - 0,0,100,2,0,25,125,1,0,100,3,0,124,0,0,107, - 7,0,114,74,0,124,1,0,106,2,0,100,4,0,131,1, - 0,100,5,0,25,125,1,0,113,74,0,110,0,0,124,1, - 0,83,40,7,0,0,0,117,167,0,0,0,67,97,108,99, - 117,108,97,116,101,32,119,104,97,116,32,95,95,112,97,99, - 107,97,103,101,95,95,32,115,104,111,117,108,100,32,98,101, - 46,10,10,32,32,32,32,95,95,112,97,99,107,97,103,101, - 95,95,32,105,115,32,110,111,116,32,103,117,97,114,97,110, - 116,101,101,100,32,116,111,32,98,101,32,100,101,102,105,110, - 101,100,32,111,114,32,99,111,117,108,100,32,98,101,32,115, - 101,116,32,116,111,32,78,111,110,101,10,32,32,32,32,116, - 111,32,114,101,112,114,101,115,101,110,116,32,116,104,97,116, - 32,105,116,115,32,112,114,111,112,101,114,32,118,97,108,117, - 101,32,105,115,32,117,110,107,110,111,119,110,46,10,10,32, - 32,32,32,117,11,0,0,0,95,95,112,97,99,107,97,103, - 101,95,95,117,8,0,0,0,95,95,110,97,109,101,95,95, - 117,8,0,0,0,95,95,112,97,116,104,95,95,117,1,0, - 0,0,46,105,0,0,0,0,78,40,3,0,0,0,117,3, - 0,0,0,103,101,116,117,4,0,0,0,78,111,110,101,117, - 10,0,0,0,114,112,97,114,116,105,116,105,111,110,40,2, - 0,0,0,117,7,0,0,0,103,108,111,98,97,108,115,117, - 7,0,0,0,112,97,99,107,97,103,101,40,0,0,0,0, - 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, - 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, - 116,115,116,114,97,112,62,117,17,0,0,0,95,99,97,108, - 99,95,95,95,112,97,99,107,97,103,101,95,95,22,4,0, - 0,115,12,0,0,0,0,7,15,1,12,1,10,1,12,1, - 25,1,117,17,0,0,0,95,99,97,108,99,95,95,95,112, - 97,99,107,97,103,101,95,95,99,5,0,0,0,0,0,0, - 0,8,0,0,0,5,0,0,0,67,0,0,0,115,204,0, - 0,0,124,4,0,100,1,0,107,2,0,114,27,0,116,0, - 0,124,0,0,131,1,0,125,5,0,110,30,0,116,1,0, - 124,1,0,131,1,0,125,6,0,116,0,0,124,0,0,124, - 6,0,124,4,0,131,3,0,125,5,0,124,3,0,115,184, - 0,124,4,0,100,1,0,107,2,0,114,99,0,116,2,0, - 106,3,0,124,0,0,106,4,0,100,2,0,131,1,0,100, - 1,0,25,25,83,124,0,0,115,109,0,124,5,0,83,116, - 5,0,124,0,0,131,1,0,116,5,0,124,0,0,106,4, - 0,100,2,0,131,1,0,100,1,0,25,131,1,0,24,125, - 7,0,116,2,0,106,3,0,124,5,0,106,6,0,100,3, - 0,116,5,0,124,5,0,106,6,0,131,1,0,124,7,0, - 24,133,2,0,25,25,83,110,16,0,116,7,0,124,5,0, - 124,3,0,116,0,0,131,3,0,83,100,3,0,83,40,4, - 0,0,0,117,214,1,0,0,73,109,112,111,114,116,32,97, - 32,109,111,100,117,108,101,46,10,10,32,32,32,32,84,104, - 101,32,39,103,108,111,98,97,108,115,39,32,97,114,103,117, - 109,101,110,116,32,105,115,32,117,115,101,100,32,116,111,32, - 105,110,102,101,114,32,119,104,101,114,101,32,116,104,101,32, - 105,109,112,111,114,116,32,105,115,32,111,99,99,117,114,105, - 110,103,32,102,114,111,109,10,32,32,32,32,116,111,32,104, - 97,110,100,108,101,32,114,101,108,97,116,105,118,101,32,105, - 109,112,111,114,116,115,46,32,84,104,101,32,39,108,111,99, - 97,108,115,39,32,97,114,103,117,109,101,110,116,32,105,115, - 32,105,103,110,111,114,101,100,46,32,84,104,101,10,32,32, - 32,32,39,102,114,111,109,108,105,115,116,39,32,97,114,103, - 117,109,101,110,116,32,115,112,101,99,105,102,105,101,115,32, - 119,104,97,116,32,115,104,111,117,108,100,32,101,120,105,115, - 116,32,97,115,32,97,116,116,114,105,98,117,116,101,115,32, - 111,110,32,116,104,101,32,109,111,100,117,108,101,10,32,32, - 32,32,98,101,105,110,103,32,105,109,112,111,114,116,101,100, - 32,40,101,46,103,46,32,96,96,102,114,111,109,32,109,111, - 100,117,108,101,32,105,109,112,111,114,116,32,60,102,114,111, - 109,108,105,115,116,62,96,96,41,46,32,32,84,104,101,32, - 39,108,101,118,101,108,39,10,32,32,32,32,97,114,103,117, - 109,101,110,116,32,114,101,112,114,101,115,101,110,116,115,32, - 116,104,101,32,112,97,99,107,97,103,101,32,108,111,99,97, - 116,105,111,110,32,116,111,32,105,109,112,111,114,116,32,102, - 114,111,109,32,105,110,32,97,32,114,101,108,97,116,105,118, - 101,10,32,32,32,32,105,109,112,111,114,116,32,40,101,46, - 103,46,32,96,96,102,114,111,109,32,46,46,112,107,103,32, - 105,109,112,111,114,116,32,109,111,100,96,96,32,119,111,117, - 108,100,32,104,97,118,101,32,97,32,39,108,101,118,101,108, - 39,32,111,102,32,50,41,46,10,10,32,32,32,32,105,0, - 0,0,0,117,1,0,0,0,46,78,40,8,0,0,0,117, - 11,0,0,0,95,103,99,100,95,105,109,112,111,114,116,117, - 17,0,0,0,95,99,97,108,99,95,95,95,112,97,99,107, - 97,103,101,95,95,117,3,0,0,0,115,121,115,117,7,0, - 0,0,109,111,100,117,108,101,115,117,9,0,0,0,112,97, - 114,116,105,116,105,111,110,117,3,0,0,0,108,101,110,117, - 8,0,0,0,95,95,110,97,109,101,95,95,117,16,0,0, - 0,95,104,97,110,100,108,101,95,102,114,111,109,108,105,115, - 116,40,8,0,0,0,117,4,0,0,0,110,97,109,101,117, - 7,0,0,0,103,108,111,98,97,108,115,117,6,0,0,0, - 108,111,99,97,108,115,117,8,0,0,0,102,114,111,109,108, - 105,115,116,117,5,0,0,0,108,101,118,101,108,117,6,0, - 0,0,109,111,100,117,108,101,117,7,0,0,0,112,97,99, - 107,97,103,101,117,7,0,0,0,99,117,116,95,111,102,102, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, - 0,95,95,105,109,112,111,114,116,95,95,37,4,0,0,115, - 24,0,0,0,0,11,12,1,15,2,12,1,18,1,6,3, - 12,1,24,1,6,1,4,2,35,1,40,2,117,10,0,0, - 0,95,95,105,109,112,111,114,116,95,95,99,2,0,0,0, - 0,0,0,0,9,0,0,0,12,0,0,0,67,0,0,0, - 115,109,1,0,0,124,1,0,97,0,0,124,0,0,97,1, - 0,120,47,0,116,0,0,116,1,0,102,2,0,68,93,33, - 0,125,2,0,116,2,0,124,2,0,100,1,0,131,2,0, - 115,25,0,116,3,0,124,2,0,95,4,0,113,25,0,113, - 25,0,87,116,1,0,106,5,0,116,6,0,25,125,3,0, - 120,76,0,100,17,0,68,93,68,0,125,4,0,124,4,0, - 116,1,0,106,5,0,107,7,0,114,121,0,116,3,0,106, - 7,0,124,4,0,131,1,0,125,5,0,110,13,0,116,1, - 0,106,5,0,124,4,0,25,125,5,0,116,8,0,124,3, - 0,124,4,0,124,5,0,131,3,0,1,113,82,0,87,120, - 153,0,100,18,0,100,19,0,100,20,0,103,3,0,68,93, - 124,0,92,2,0,125,6,0,125,7,0,124,6,0,116,1, - 0,106,5,0,107,6,0,114,214,0,116,1,0,106,5,0, - 124,6,0,25,125,8,0,80,113,170,0,121,56,0,116,3, - 0,106,7,0,124,6,0,131,1,0,125,8,0,124,6,0, - 100,10,0,107,2,0,114,12,1,100,11,0,116,1,0,106, - 9,0,107,6,0,114,12,1,100,7,0,125,7,0,110,0, - 0,80,87,113,170,0,4,116,10,0,107,10,0,114,37,1, - 1,1,1,119,170,0,89,113,170,0,88,113,170,0,87,116, - 10,0,100,12,0,131,1,0,130,1,0,116,8,0,124,3, - 0,100,13,0,124,8,0,131,3,0,1,116,8,0,124,3, - 0,100,14,0,124,7,0,131,3,0,1,116,8,0,124,3, - 0,100,15,0,116,11,0,131,0,0,131,3,0,1,100,16, - 0,83,40,21,0,0,0,117,249,0,0,0,83,101,116,117, - 112,32,105,109,112,111,114,116,108,105,98,32,98,121,32,105, - 109,112,111,114,116,105,110,103,32,110,101,101,100,101,100,32, - 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,115, - 32,97,110,100,32,105,110,106,101,99,116,105,110,103,32,116, - 104,101,109,10,32,32,32,32,105,110,116,111,32,116,104,101, - 32,103,108,111,98,97,108,32,110,97,109,101,115,112,97,99, - 101,46,10,10,32,32,32,32,65,115,32,115,121,115,32,105, - 115,32,110,101,101,100,101,100,32,102,111,114,32,115,121,115, - 46,109,111,100,117,108,101,115,32,97,99,99,101,115,115,32, - 97,110,100,32,105,109,112,32,105,115,32,110,101,101,100,101, - 100,32,116,111,32,108,111,97,100,32,98,117,105,108,116,45, - 105,110,10,32,32,32,32,109,111,100,117,108,101,115,44,32, - 116,104,111,115,101,32,116,119,111,32,109,111,100,117,108,101, - 115,32,109,117,115,116,32,98,101,32,101,120,112,108,105,99, - 105,116,108,121,32,112,97,115,115,101,100,32,105,110,46,10, - 10,32,32,32,32,117,10,0,0,0,95,95,108,111,97,100, - 101,114,95,95,117,3,0,0,0,95,105,111,117,9,0,0, - 0,95,119,97,114,110,105,110,103,115,117,8,0,0,0,98, - 117,105,108,116,105,110,115,117,7,0,0,0,109,97,114,115, - 104,97,108,117,5,0,0,0,112,111,115,105,120,117,1,0, - 0,0,47,117,2,0,0,0,110,116,117,1,0,0,0,92, - 117,3,0,0,0,111,115,50,117,7,0,0,0,69,77,88, - 32,71,67,67,117,30,0,0,0,105,109,112,111,114,116,108, - 105,98,32,114,101,113,117,105,114,101,115,32,112,111,115,105, - 120,32,111,114,32,110,116,117,3,0,0,0,95,111,115,117, - 8,0,0,0,112,97,116,104,95,115,101,112,117,11,0,0, - 0,95,114,101,108,97,120,95,99,97,115,101,78,40,4,0, - 0,0,117,3,0,0,0,95,105,111,117,9,0,0,0,95, - 119,97,114,110,105,110,103,115,117,8,0,0,0,98,117,105, - 108,116,105,110,115,117,7,0,0,0,109,97,114,115,104,97, - 108,40,2,0,0,0,117,5,0,0,0,112,111,115,105,120, - 117,1,0,0,0,47,40,2,0,0,0,117,2,0,0,0, - 110,116,117,1,0,0,0,92,40,2,0,0,0,117,3,0, - 0,0,111,115,50,117,1,0,0,0,92,40,12,0,0,0, - 117,3,0,0,0,105,109,112,117,3,0,0,0,115,121,115, - 117,7,0,0,0,104,97,115,97,116,116,114,117,15,0,0, - 0,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, - 117,10,0,0,0,95,95,108,111,97,100,101,114,95,95,117, - 7,0,0,0,109,111,100,117,108,101,115,117,8,0,0,0, - 95,95,110,97,109,101,95,95,117,11,0,0,0,108,111,97, - 100,95,109,111,100,117,108,101,117,7,0,0,0,115,101,116, - 97,116,116,114,117,7,0,0,0,118,101,114,115,105,111,110, - 117,11,0,0,0,73,109,112,111,114,116,69,114,114,111,114, + 62,117,6,0,0,0,95,115,101,116,117,112,71,4,0,0, + 115,52,0,0,0,0,9,6,1,6,2,19,1,15,1,16, + 2,13,1,13,1,15,1,18,2,13,1,20,2,28,1,15, + 1,13,1,4,2,3,1,15,2,27,1,9,1,5,1,13, + 1,12,2,12,1,16,1,16,2,117,6,0,0,0,95,115, + 101,116,117,112,99,2,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,67,0,0,0,115,44,0,0,0,116,0, + 0,124,0,0,124,1,0,131,2,0,1,116,1,0,106,2, + 0,125,2,0,116,2,0,116,1,0,95,2,0,124,2,0, + 116,1,0,95,3,0,100,1,0,83,40,2,0,0,0,117, + 201,0,0,0,73,110,115,116,97,108,108,32,105,109,112,111, + 114,116,108,105,98,32,97,115,32,116,104,101,32,105,109,112, + 108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,105, + 109,112,111,114,116,46,10,10,32,32,32,32,73,116,32,105, + 115,32,97,115,115,117,109,101,100,32,116,104,97,116,32,105, + 109,112,32,97,110,100,32,115,121,115,32,104,97,118,101,32, + 98,101,101,110,32,105,109,112,111,114,116,101,100,32,97,110, + 100,32,105,110,106,101,99,116,101,100,32,105,110,116,111,32, + 116,104,101,10,32,32,32,32,103,108,111,98,97,108,32,110, + 97,109,101,115,112,97,99,101,32,102,111,114,32,116,104,101, + 32,109,111,100,117,108,101,32,112,114,105,111,114,32,116,111, + 32,99,97,108,108,105,110,103,32,116,104,105,115,32,102,117, + 110,99,116,105,111,110,46,10,10,32,32,32,32,78,40,4, + 0,0,0,117,6,0,0,0,95,115,101,116,117,112,117,8, + 0,0,0,98,117,105,108,116,105,110,115,117,10,0,0,0, + 95,95,105,109,112,111,114,116,95,95,117,19,0,0,0,95, + 95,111,114,105,103,105,110,97,108,95,105,109,112,111,114,116, + 95,95,40,3,0,0,0,117,10,0,0,0,115,121,115,95, + 109,111,100,117,108,101,117,10,0,0,0,105,109,112,95,109, + 111,100,117,108,101,117,11,0,0,0,111,114,105,103,95,105, + 109,112,111,114,116,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,8,0,0,0,95,105,110,115,116,97,108,108,116,4, + 0,0,115,8,0,0,0,0,7,13,1,9,1,9,1,117, + 8,0,0,0,95,105,110,115,116,97,108,108,78,40,3,0, + 0,0,117,3,0,0,0,119,105,110,117,6,0,0,0,99, + 121,103,119,105,110,117,6,0,0,0,100,97,114,119,105,110, + 40,55,0,0,0,117,7,0,0,0,95,95,100,111,99,95, + 95,117,26,0,0,0,67,65,83,69,95,73,78,83,69,78, + 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, 117,16,0,0,0,95,109,97,107,101,95,114,101,108,97,120, - 95,99,97,115,101,40,9,0,0,0,117,10,0,0,0,115, - 121,115,95,109,111,100,117,108,101,117,10,0,0,0,105,109, - 112,95,109,111,100,117,108,101,117,6,0,0,0,109,111,100, - 117,108,101,117,11,0,0,0,115,101,108,102,95,109,111,100, - 117,108,101,117,12,0,0,0,98,117,105,108,116,105,110,95, - 110,97,109,101,117,14,0,0,0,98,117,105,108,116,105,110, - 95,109,111,100,117,108,101,117,10,0,0,0,98,117,105,108, - 116,105,110,95,111,115,117,8,0,0,0,112,97,116,104,95, - 115,101,112,117,9,0,0,0,111,115,95,109,111,100,117,108, - 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,6,0, - 0,0,95,115,101,116,117,112,67,4,0,0,115,52,0,0, - 0,0,9,6,1,6,2,19,1,15,1,16,2,13,1,13, - 1,15,1,18,2,13,1,20,2,28,1,15,1,13,1,4, - 2,3,1,15,2,27,1,9,1,5,1,13,1,12,2,12, - 1,16,1,16,2,117,6,0,0,0,95,115,101,116,117,112, - 99,2,0,0,0,0,0,0,0,3,0,0,0,3,0,0, - 0,67,0,0,0,115,44,0,0,0,116,0,0,124,0,0, - 124,1,0,131,2,0,1,116,1,0,106,2,0,125,2,0, - 116,2,0,116,1,0,95,2,0,124,2,0,116,1,0,95, - 3,0,100,1,0,83,40,2,0,0,0,117,201,0,0,0, - 73,110,115,116,97,108,108,32,105,109,112,111,114,116,108,105, - 98,32,97,115,32,116,104,101,32,105,109,112,108,101,109,101, - 110,116,97,116,105,111,110,32,111,102,32,105,109,112,111,114, - 116,46,10,10,32,32,32,32,73,116,32,105,115,32,97,115, - 115,117,109,101,100,32,116,104,97,116,32,105,109,112,32,97, - 110,100,32,115,121,115,32,104,97,118,101,32,98,101,101,110, - 32,105,109,112,111,114,116,101,100,32,97,110,100,32,105,110, - 106,101,99,116,101,100,32,105,110,116,111,32,116,104,101,10, - 32,32,32,32,103,108,111,98,97,108,32,110,97,109,101,115, - 112,97,99,101,32,102,111,114,32,116,104,101,32,109,111,100, - 117,108,101,32,112,114,105,111,114,32,116,111,32,99,97,108, - 108,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105, - 111,110,46,10,10,32,32,32,32,78,40,4,0,0,0,117, - 6,0,0,0,95,115,101,116,117,112,117,8,0,0,0,98, - 117,105,108,116,105,110,115,117,10,0,0,0,95,95,105,109, - 112,111,114,116,95,95,117,19,0,0,0,95,95,111,114,105, - 103,105,110,97,108,95,105,109,112,111,114,116,95,95,40,3, - 0,0,0,117,10,0,0,0,115,121,115,95,109,111,100,117, - 108,101,117,10,0,0,0,105,109,112,95,109,111,100,117,108, - 101,117,11,0,0,0,111,114,105,103,95,105,109,112,111,114, - 116,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, - 0,0,95,105,110,115,116,97,108,108,112,4,0,0,115,8, - 0,0,0,0,7,13,1,9,1,9,1,117,8,0,0,0, - 95,105,110,115,116,97,108,108,78,40,3,0,0,0,117,3, - 0,0,0,119,105,110,117,6,0,0,0,99,121,103,119,105, - 110,117,6,0,0,0,100,97,114,119,105,110,40,55,0,0, - 0,117,7,0,0,0,95,95,100,111,99,95,95,117,26,0, - 0,0,67,65,83,69,95,73,78,83,69,78,83,73,84,73, - 86,69,95,80,76,65,84,70,79,82,77,83,117,16,0,0, - 0,95,109,97,107,101,95,114,101,108,97,120,95,99,97,115, - 101,117,7,0,0,0,95,119,95,108,111,110,103,117,7,0, - 0,0,95,114,95,108,111,110,103,117,10,0,0,0,95,112, - 97,116,104,95,106,111,105,110,117,12,0,0,0,95,112,97, - 116,104,95,101,120,105,115,116,115,117,18,0,0,0,95,112, - 97,116,104,95,105,115,95,109,111,100,101,95,116,121,112,101, - 117,12,0,0,0,95,112,97,116,104,95,105,115,102,105,108, - 101,117,11,0,0,0,95,112,97,116,104,95,105,115,100,105, - 114,117,17,0,0,0,95,112,97,116,104,95,119,105,116,104, - 111,117,116,95,101,120,116,117,14,0,0,0,95,112,97,116, - 104,95,97,98,115,111,108,117,116,101,117,13,0,0,0,95, - 119,114,105,116,101,95,97,116,111,109,105,99,117,5,0,0, - 0,95,119,114,97,112,117,4,0,0,0,116,121,112,101,117, - 8,0,0,0,95,95,99,111,100,101,95,95,117,9,0,0, - 0,99,111,100,101,95,116,121,112,101,117,15,0,0,0,118, - 101,114,98,111,115,101,95,109,101,115,115,97,103,101,117,11, - 0,0,0,115,101,116,95,112,97,99,107,97,103,101,117,10, - 0,0,0,115,101,116,95,108,111,97,100,101,114,117,17,0, - 0,0,109,111,100,117,108,101,95,102,111,114,95,108,111,97, - 100,101,114,117,11,0,0,0,95,99,104,101,99,107,95,110, - 97,109,101,117,17,0,0,0,95,114,101,113,117,105,114,101, - 115,95,98,117,105,108,116,105,110,117,16,0,0,0,95,114, - 101,113,117,105,114,101,115,95,102,114,111,122,101,110,117,12, - 0,0,0,95,115,117,102,102,105,120,95,108,105,115,116,117, - 15,0,0,0,66,117,105,108,116,105,110,73,109,112,111,114, - 116,101,114,117,14,0,0,0,70,114,111,122,101,110,73,109, - 112,111,114,116,101,114,117,13,0,0,0,95,76,111,97,100, - 101,114,66,97,115,105,99,115,117,12,0,0,0,83,111,117, - 114,99,101,76,111,97,100,101,114,117,11,0,0,0,95,70, - 105,108,101,76,111,97,100,101,114,117,17,0,0,0,95,83, - 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,117, - 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, - 105,108,101,76,111,97,100,101,114,117,20,0,0,0,95,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,117,10,0,0,0,80,97,116,104,70,105,110,100,101, - 114,117,11,0,0,0,95,70,105,108,101,70,105,110,100,101, - 114,117,20,0,0,0,95,83,111,117,114,99,101,70,105,110, - 100,101,114,68,101,116,97,105,108,115,117,24,0,0,0,95, - 83,111,117,114,99,101,108,101,115,115,70,105,110,100,101,114, - 68,101,116,97,105,108,115,117,23,0,0,0,95,69,120,116, - 101,110,115,105,111,110,70,105,110,100,101,114,68,101,116,97, - 105,108,115,117,15,0,0,0,95,102,105,108,101,95,112,97, - 116,104,95,104,111,111,107,117,18,0,0,0,95,68,69,70, - 65,85,76,84,95,80,65,84,72,95,72,79,79,75,117,18, - 0,0,0,95,68,101,102,97,117,108,116,80,97,116,104,70, - 105,110,100,101,114,117,18,0,0,0,95,73,109,112,111,114, - 116,76,111,99,107,67,111,110,116,101,120,116,117,13,0,0, - 0,95,114,101,115,111,108,118,101,95,110,97,109,101,117,12, - 0,0,0,95,102,105,110,100,95,109,111,100,117,108,101,117, - 13,0,0,0,95,115,97,110,105,116,121,95,99,104,101,99, - 107,117,19,0,0,0,95,73,77,80,76,73,67,73,84,95, - 77,69,84,65,95,80,65,84,72,117,8,0,0,0,95,69, - 82,82,95,77,83,71,117,14,0,0,0,95,102,105,110,100, - 95,97,110,100,95,108,111,97,100,117,4,0,0,0,78,111, - 110,101,117,11,0,0,0,95,103,99,100,95,105,109,112,111, - 114,116,117,16,0,0,0,95,104,97,110,100,108,101,95,102, - 114,111,109,108,105,115,116,117,17,0,0,0,95,99,97,108, - 99,95,95,95,112,97,99,107,97,103,101,95,95,117,10,0, - 0,0,95,95,105,109,112,111,114,116,95,95,117,6,0,0, - 0,95,115,101,116,117,112,117,8,0,0,0,95,105,110,115, - 116,97,108,108,40,0,0,0,0,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,8,0,0,0,60,109,111,100,117,108, - 101,62,8,0,0,0,115,102,0,0,0,6,14,6,3,12, - 13,12,16,12,15,12,6,12,10,12,10,12,6,12,7,12, - 9,12,13,12,21,12,8,15,4,12,8,12,13,12,11,12, - 32,12,16,12,11,12,11,12,8,19,53,19,47,19,77,22, - 114,19,22,25,38,25,24,19,45,19,68,19,77,19,8,19, - 9,19,11,12,10,6,2,22,21,19,13,12,9,12,15,12, - 17,15,2,6,2,12,41,18,25,12,23,12,15,24,30,12, - 45, + 95,99,97,115,101,117,7,0,0,0,95,119,95,108,111,110, + 103,117,7,0,0,0,95,114,95,108,111,110,103,117,10,0, + 0,0,95,112,97,116,104,95,106,111,105,110,117,12,0,0, + 0,95,112,97,116,104,95,101,120,105,115,116,115,117,18,0, + 0,0,95,112,97,116,104,95,105,115,95,109,111,100,101,95, + 116,121,112,101,117,12,0,0,0,95,112,97,116,104,95,105, + 115,102,105,108,101,117,11,0,0,0,95,112,97,116,104,95, + 105,115,100,105,114,117,17,0,0,0,95,112,97,116,104,95, + 119,105,116,104,111,117,116,95,101,120,116,117,14,0,0,0, + 95,112,97,116,104,95,97,98,115,111,108,117,116,101,117,13, + 0,0,0,95,119,114,105,116,101,95,97,116,111,109,105,99, + 117,5,0,0,0,95,119,114,97,112,117,4,0,0,0,116, + 121,112,101,117,8,0,0,0,95,95,99,111,100,101,95,95, + 117,9,0,0,0,99,111,100,101,95,116,121,112,101,117,15, + 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, + 103,101,117,11,0,0,0,115,101,116,95,112,97,99,107,97, + 103,101,117,10,0,0,0,115,101,116,95,108,111,97,100,101, + 114,117,17,0,0,0,109,111,100,117,108,101,95,102,111,114, + 95,108,111,97,100,101,114,117,11,0,0,0,95,99,104,101, + 99,107,95,110,97,109,101,117,17,0,0,0,95,114,101,113, + 117,105,114,101,115,95,98,117,105,108,116,105,110,117,16,0, + 0,0,95,114,101,113,117,105,114,101,115,95,102,114,111,122, + 101,110,117,12,0,0,0,95,115,117,102,102,105,120,95,108, + 105,115,116,117,15,0,0,0,66,117,105,108,116,105,110,73, + 109,112,111,114,116,101,114,117,14,0,0,0,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,117,13,0,0,0,95, + 76,111,97,100,101,114,66,97,115,105,99,115,117,12,0,0, + 0,83,111,117,114,99,101,76,111,97,100,101,114,117,11,0, + 0,0,95,70,105,108,101,76,111,97,100,101,114,117,17,0, + 0,0,95,83,111,117,114,99,101,70,105,108,101,76,111,97, + 100,101,114,117,21,0,0,0,95,83,111,117,114,99,101,108, + 101,115,115,70,105,108,101,76,111,97,100,101,114,117,20,0, + 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,117,10,0,0,0,80,97,116,104,70, + 105,110,100,101,114,117,11,0,0,0,95,70,105,108,101,70, + 105,110,100,101,114,117,20,0,0,0,95,83,111,117,114,99, + 101,70,105,110,100,101,114,68,101,116,97,105,108,115,117,24, + 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, + 110,100,101,114,68,101,116,97,105,108,115,117,23,0,0,0, + 95,69,120,116,101,110,115,105,111,110,70,105,110,100,101,114, + 68,101,116,97,105,108,115,117,15,0,0,0,95,102,105,108, + 101,95,112,97,116,104,95,104,111,111,107,117,18,0,0,0, + 95,68,69,70,65,85,76,84,95,80,65,84,72,95,72,79, + 79,75,117,18,0,0,0,95,68,101,102,97,117,108,116,80, + 97,116,104,70,105,110,100,101,114,117,18,0,0,0,95,73, + 109,112,111,114,116,76,111,99,107,67,111,110,116,101,120,116, + 117,13,0,0,0,95,114,101,115,111,108,118,101,95,110,97, + 109,101,117,12,0,0,0,95,102,105,110,100,95,109,111,100, + 117,108,101,117,13,0,0,0,95,115,97,110,105,116,121,95, + 99,104,101,99,107,117,19,0,0,0,95,73,77,80,76,73, + 67,73,84,95,77,69,84,65,95,80,65,84,72,117,8,0, + 0,0,95,69,82,82,95,77,83,71,117,14,0,0,0,95, + 102,105,110,100,95,97,110,100,95,108,111,97,100,117,4,0, + 0,0,78,111,110,101,117,11,0,0,0,95,103,99,100,95, + 105,109,112,111,114,116,117,16,0,0,0,95,104,97,110,100, + 108,101,95,102,114,111,109,108,105,115,116,117,17,0,0,0, + 95,99,97,108,99,95,95,95,112,97,99,107,97,103,101,95, + 95,117,10,0,0,0,95,95,105,109,112,111,114,116,95,95, + 117,6,0,0,0,95,115,101,116,117,112,117,8,0,0,0, + 95,105,110,115,116,97,108,108,40,0,0,0,0,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,8,0,0,0,60,109, + 111,100,117,108,101,62,8,0,0,0,115,102,0,0,0,6, + 14,6,3,12,13,12,16,12,15,12,6,12,10,12,10,12, + 6,12,7,12,9,12,13,12,21,12,8,15,4,12,8,12, + 13,12,11,12,32,12,16,12,11,12,11,12,8,19,53,19, + 47,19,77,22,114,19,22,25,38,25,24,19,45,19,68,19, + 77,19,8,19,9,19,11,12,10,6,2,22,21,19,13,12, + 9,12,15,12,17,15,2,6,2,12,41,18,25,12,23,12, + 15,24,34,12,45, }; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 21:25:27 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 21:25:27 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/95c29787320a changeset: 76330:95c29787320a parent: 76329:005fd1fe31ab parent: 76327:1ca10eb58483 user: Brett Cannon date: Sun Apr 15 15:25:10 2012 -0400 summary: merge files: Lib/importlib/_bootstrap.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -23,7 +23,7 @@ def _make_relax_case(): - if any(map(sys.platform.startswith, CASE_INSENSITIVE_PLATFORMS)): + if sys.platform.startswith(CASE_INSENSITIVE_PLATFORMS): def _relax_case(): """True if filenames must be checked case-insensitively.""" return b'PYTHONCASEOK' in _os.environ @@ -163,7 +163,7 @@ def verbose_message(message, *args): """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" if sys.flags.verbose: - if not message.startswith('#') and not message.startswith('import '): + if not message.startswith(('#', 'import ')): message = '# ' + message print(message.format(*args), file=sys.stderr) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 22:09:10 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 22:09:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Rename_im?= =?utf8?q?p_to_=5Fimp_and_add_Lib/imp=2Epy_and_begin?= Message-ID: http://hg.python.org/cpython/rev/d777f854a66e changeset: 76331:d777f854a66e user: Brett Cannon date: Sun Apr 15 16:08:47 2012 -0400 summary: Issue #13959: Rename imp to _imp and add Lib/imp.py and begin rewriting functionality in pure Python. To start, imp.new_module() has been rewritten in pure Python, put into importlib (privately) and then publicly exposed in imp. files: Lib/imp.py | 22 + Lib/importlib/_bootstrap.py | 70 +- Misc/NEWS | 3 + Modules/config.c.in | 2 +- PC/config.c | 2 +- PC/os2emx/config.c | 2 +- PC/os2vacpp/config.c | 2 +- Python/import.c | 20 +- Python/importlib.h | 5555 +++++++++++----------- Python/pythonrun.c | 4 +- 10 files changed, 2859 insertions(+), 2823 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py new file mode 100644 --- /dev/null +++ b/Lib/imp.py @@ -0,0 +1,22 @@ +"""This module provides the components needed to build your own __import__ +function. Undocumented functions are obsolete. + +In most cases it is preferred you consider using the importlib module's +functionality over this module. + +""" +# (Probably) need to stay in _imp +from _imp import (lock_held, acquire_lock, release_lock, reload, + get_frozen_object, is_frozen_package, init_builtin, + init_frozen, is_builtin, is_frozen, _fix_co_filename) +# Can (probably) move to importlib +from _imp import (get_magic, get_tag, get_suffixes, cache_from_source, + source_from_cache) +# Should be re-implemented here (and mostly deprecated) +from _imp import (find_module, load_module, load_compiled, load_dynamic, + load_package, load_source, NullImporter, + SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, + PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, + PY_CODERESOURCE, IMP_HOOK) + +from importlib._bootstrap import _new_module as new_module diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -7,7 +7,7 @@ """ -# Injected modules are '_warnings', 'imp', 'sys', 'marshal', '_io', +# Injected modules are '_warnings', '_imp', 'sys', 'marshal', '_io', # and '_os' (a.k.a. 'posix', 'nt' or 'os2'). # Injected attribute is path_sep. # Most injection is handled by _setup(). @@ -158,6 +158,16 @@ code_type = type(_wrap.__code__) + +def _new_module(name): + """Create a new module. + + The module is not entered into sys.modules. + + """ + return type(sys)(name) + + # Finder/loader utility code ################################################## def verbose_message(message, *args): @@ -212,7 +222,7 @@ # This must be done before open() is called as the 'io' module # implicitly imports 'locale' and would otherwise trigger an # infinite loop. - module = imp.new_module(fullname) + module = _new_module(fullname) sys.modules[fullname] = module try: return fxn(self, module, *args, **kwargs) @@ -254,7 +264,7 @@ def _requires_frozen(fxn): """Decorator to verify the named module is frozen.""" def _requires_frozen_wrapper(self, fullname): - if not imp.is_frozen(fullname): + if not _imp.is_frozen(fullname): raise ImportError("{0} is not a frozen module".format(fullname), name=fullname) return fxn(self, fullname) @@ -264,7 +274,7 @@ def _suffix_list(suffix_type): """Return a list of file suffixes based on the imp file type.""" - return [suffix[0] for suffix in imp.get_suffixes() + return [suffix[0] for suffix in _imp.get_suffixes() if suffix[2] == suffix_type] @@ -288,7 +298,7 @@ """ if path is not None: return None - return cls if imp.is_builtin(fullname) else None + return cls if _imp.is_builtin(fullname) else None @classmethod @set_package @@ -298,7 +308,7 @@ """Load a built-in module.""" is_reload = fullname in sys.modules try: - return imp.init_builtin(fullname) + return _imp.init_builtin(fullname) except: if not is_reload and fullname in sys.modules: del sys.modules[fullname] @@ -335,7 +345,7 @@ @classmethod def find_module(cls, fullname, path=None): """Find a frozen module.""" - return cls if imp.is_frozen(fullname) else None + return cls if _imp.is_frozen(fullname) else None @classmethod @set_package @@ -345,7 +355,7 @@ """Load a frozen module.""" is_reload = fullname in sys.modules try: - return imp.init_frozen(fullname) + return _imp.init_frozen(fullname) except: if not is_reload and fullname in sys.modules: del sys.modules[fullname] @@ -355,7 +365,7 @@ @_requires_frozen def get_code(cls, fullname): """Return the code object for the frozen module.""" - return imp.get_frozen_object(fullname) + return _imp.get_frozen_object(fullname) @classmethod @_requires_frozen @@ -367,7 +377,7 @@ @_requires_frozen def is_package(cls, fullname): """Return if the frozen module is a package.""" - return imp.is_frozen_package(fullname) + return _imp.is_frozen_package(fullname) class _LoaderBasics: @@ -391,7 +401,7 @@ magic = data[:4] raw_timestamp = data[4:8] raw_size = data[8:12] - if len(magic) != 4 or magic != imp.get_magic(): + if len(magic) != 4 or magic != _imp.get_magic(): raise ImportError("bad magic number in {}".format(fullname), name=fullname, path=bytecode_path) elif len(raw_timestamp) != 4: @@ -434,7 +444,7 @@ code_object = self.get_code(name) module.__file__ = self.get_filename(name) if not sourceless: - module.__cached__ = imp.cache_from_source(module.__file__) + module.__cached__ = _imp.cache_from_source(module.__file__) else: module.__cached__ = module.__file__ module.__package__ = name @@ -497,7 +507,7 @@ """ source_path = self.get_filename(fullname) - bytecode_path = imp.cache_from_source(source_path) + bytecode_path = _imp.cache_from_source(source_path) source_mtime = None if bytecode_path is not None: try: @@ -522,7 +532,7 @@ source_path) found = marshal.loads(bytes_data) if isinstance(found, code_type): - imp._fix_co_filename(found, source_path) + _imp._fix_co_filename(found, source_path) verbose_message('code object from {}', bytecode_path) return found @@ -539,7 +549,7 @@ # If e.g. Jython ever implements imp.cache_from_source to have # their own cached file format, this block of code will most likely # throw an exception. - data = bytearray(imp.get_magic()) + data = bytearray(_imp.get_magic()) data.extend(_w_long(source_mtime)) data.extend(_w_long(len(source_bytes))) data.extend(marshal.dumps(code_object)) @@ -664,7 +674,7 @@ """Load an extension module.""" is_reload = fullname in sys.modules try: - module = imp.load_dynamic(fullname, self._path) + module = _imp.load_dynamic(fullname, self._path) verbose_message('extension module loaded from {!r}', self._path) return module except: @@ -841,7 +851,7 @@ supports_packages = True def __init__(self): - self.suffixes = _suffix_list(imp.PY_SOURCE) + self.suffixes = _suffix_list(_imp.PY_SOURCE) class _SourcelessFinderDetails: @@ -849,7 +859,7 @@ supports_packages = True def __init__(self): - self.suffixes = _suffix_list(imp.PY_COMPILED) + self.suffixes = _suffix_list(_imp.PY_COMPILED) class _ExtensionFinderDetails: @@ -858,7 +868,7 @@ supports_packages = False def __init__(self): - self.suffixes = _suffix_list(imp.C_EXTENSION) + self.suffixes = _suffix_list(_imp.C_EXTENSION) # Import itself ############################################################### @@ -886,7 +896,7 @@ try: return super()._path_hooks(path) except ImportError: - implicit_hooks = [_DEFAULT_PATH_HOOK, imp.NullImporter] + implicit_hooks = [_DEFAULT_PATH_HOOK, _imp.NullImporter] return super()._path_hooks(path, implicit_hooks) @classmethod @@ -902,11 +912,11 @@ def __enter__(self): """Acquire the import lock.""" - imp.acquire_lock() + _imp.acquire_lock() def __exit__(self, exc_type, exc_value, exc_traceback): """Release the import lock regardless of any raised exceptions.""" - imp.release_lock() + _imp.release_lock() def _resolve_name(name, package, level): @@ -1092,19 +1102,19 @@ return _handle_fromlist(module, fromlist, _gcd_import) -def _setup(sys_module, imp_module): +def _setup(sys_module, _imp_module): """Setup importlib by importing needed built-in modules and injecting them into the global namespace. - As sys is needed for sys.modules access and imp is needed to load built-in + As sys is needed for sys.modules access and _imp is needed to load built-in modules, those two modules must be explicitly passed in. """ - global imp, sys - imp = imp_module + global _imp, sys + _imp = _imp_module sys = sys_module - for module in (imp, sys): + for module in (_imp, sys): if not hasattr(module, '__loader__'): module.__loader__ = BuiltinImporter @@ -1137,14 +1147,14 @@ setattr(self_module, '_relax_case', _make_relax_case()) -def _install(sys_module, imp_module): +def _install(sys_module, _imp_module): """Install importlib as the implementation of import. - It is assumed that imp and sys have been imported and injected into the + It is assumed that _imp and sys have been imported and injected into the global namespace for the module prior to calling this function. """ - _setup(sys_module, imp_module) + _setup(sys_module, _imp_module) orig_import = builtins.__import__ builtins.__import__ = __import__ builtins.__original_import__ = orig_import diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Library ------- +- Issue #13959: Add imp.py and rename the built-in module to _imp, allowing for + re-implementing parts of the module in pure Python. + - Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied to a collection of size > sys.maxsize / 2. diff --git a/Modules/config.c.in b/Modules/config.c.in --- a/Modules/config.c.in +++ b/Modules/config.c.in @@ -39,7 +39,7 @@ {"marshal", PyMarshal_Init}, /* This lives in import.c */ - {"imp", PyInit_imp}, + {"_imp", PyInit_imp}, /* This lives in Python/Python-ast.c */ {"_ast", PyInit__ast}, diff --git a/PC/config.c b/PC/config.c --- a/PC/config.c +++ b/PC/config.c @@ -143,7 +143,7 @@ {"marshal", PyMarshal_Init}, /* This lives it with import.c */ - {"imp", PyInit_imp}, + {"_imp", PyInit_imp}, /* These entries are here for sys.builtin_module_names */ {"__main__", NULL}, diff --git a/PC/os2emx/config.c b/PC/os2emx/config.c --- a/PC/os2emx/config.c +++ b/PC/os2emx/config.c @@ -150,7 +150,7 @@ {"marshal", PyMarshal_Init}, /* This lives it with import.c */ - {"imp", initimp}, + {"_imp", initimp}, /* These entries are here for sys.builtin_module_names */ {"__main__", NULL}, diff --git a/PC/os2vacpp/config.c b/PC/os2vacpp/config.c --- a/PC/os2vacpp/config.c +++ b/PC/os2vacpp/config.c @@ -88,7 +88,7 @@ {"marshal", PyMarshal_Init}, /* This lives it with import.c */ - {"imp", initimp}, + {"_imp", initimp}, /* These entries are here for sys.builtin_module_names */ {"__main__", NULL}, diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -3685,15 +3685,6 @@ } static PyObject * -imp_new_module(PyObject *self, PyObject *args) -{ - PyObject *name; - if (!PyArg_ParseTuple(args, "U:new_module", &name)) - return NULL; - return PyModule_NewObject(name); -} - -static PyObject * imp_reload(PyObject *self, PyObject *v) { return PyImport_ReloadModule(v); @@ -3781,8 +3772,7 @@ /* Doc strings */ PyDoc_STRVAR(doc_imp, -"This module provides the components needed to build your own\n\ -__import__ function. Undocumented functions are obsolete."); +"(Extremely) low-level import machinery bits as used by importlib and imp."); PyDoc_STRVAR(doc_find_module, "find_module(name, [path]) -> (file, filename, (suffix, mode, type))\n\ @@ -3809,11 +3799,6 @@ Return a list of (suffix, mode, type) tuples describing the files\n\ that find_module() looks for."); -PyDoc_STRVAR(doc_new_module, -"new_module(name) -> module\n\ -Create a new module. Do not enter it in sys.modules.\n\ -The module name must include the full package name, if any."); - PyDoc_STRVAR(doc_lock_held, "lock_held() -> boolean\n\ Return True if the import lock is currently held, else False.\n\ @@ -3837,7 +3822,6 @@ {"get_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, {"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes}, {"load_module", imp_load_module, METH_VARARGS, doc_load_module}, - {"new_module", imp_new_module, METH_VARARGS, doc_new_module}, {"lock_held", imp_lock_held, METH_NOARGS, doc_lock_held}, {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, @@ -4005,7 +3989,7 @@ static struct PyModuleDef impmodule = { PyModuleDef_HEAD_INIT, - "imp", + "_imp", doc_imp, 0, imp_methods, diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h @@ -1,8 +1,8 @@ /* Auto-generated by Python/freeze_importlib.py */ unsigned char _Py_M__importlib[] = { 99,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0, - 0,64,0,0,0,115,239,2,0,0,100,0,0,90,0,0, - 100,99,0,90,1,0,100,4,0,100,5,0,132,0,0,90, + 0,64,0,0,0,115,251,2,0,0,100,0,0,90,0,0, + 100,101,0,90,1,0,100,4,0,100,5,0,132,0,0,90, 2,0,100,6,0,100,7,0,132,0,0,90,3,0,100,8, 0,100,9,0,132,0,0,90,4,0,100,10,0,100,11,0, 132,0,0,90,5,0,100,12,0,100,13,0,132,0,0,90, @@ -18,1137 +18,1152 @@ 0,0,90,20,0,100,36,0,100,37,0,132,0,0,90,21, 0,100,38,0,100,39,0,132,0,0,90,22,0,100,40,0, 100,41,0,132,0,0,90,23,0,100,42,0,100,43,0,132, - 0,0,90,24,0,71,100,44,0,100,45,0,132,0,0,100, - 45,0,131,2,0,90,25,0,71,100,46,0,100,47,0,132, - 0,0,100,47,0,131,2,0,90,26,0,71,100,48,0,100, - 49,0,132,0,0,100,49,0,131,2,0,90,27,0,71,100, - 50,0,100,51,0,132,0,0,100,51,0,101,27,0,131,3, - 0,90,28,0,71,100,52,0,100,53,0,132,0,0,100,53, - 0,131,2,0,90,29,0,71,100,54,0,100,55,0,132,0, - 0,100,55,0,101,29,0,101,28,0,131,4,0,90,30,0, - 71,100,56,0,100,57,0,132,0,0,100,57,0,101,29,0, - 101,27,0,131,4,0,90,31,0,71,100,58,0,100,59,0, - 132,0,0,100,59,0,131,2,0,90,32,0,71,100,60,0, - 100,61,0,132,0,0,100,61,0,131,2,0,90,33,0,71, - 100,62,0,100,63,0,132,0,0,100,63,0,131,2,0,90, - 34,0,71,100,64,0,100,65,0,132,0,0,100,65,0,131, - 2,0,90,35,0,71,100,66,0,100,67,0,132,0,0,100, - 67,0,131,2,0,90,36,0,71,100,68,0,100,69,0,132, - 0,0,100,69,0,131,2,0,90,37,0,100,70,0,100,71, - 0,132,0,0,90,38,0,101,38,0,90,39,0,71,100,72, - 0,100,73,0,132,0,0,100,73,0,101,33,0,131,3,0, - 90,40,0,71,100,74,0,100,75,0,132,0,0,100,75,0, - 131,2,0,90,41,0,100,76,0,100,77,0,132,0,0,90, + 0,0,90,24,0,100,44,0,100,45,0,132,0,0,90,25, + 0,71,100,46,0,100,47,0,132,0,0,100,47,0,131,2, + 0,90,26,0,71,100,48,0,100,49,0,132,0,0,100,49, + 0,131,2,0,90,27,0,71,100,50,0,100,51,0,132,0, + 0,100,51,0,131,2,0,90,28,0,71,100,52,0,100,53, + 0,132,0,0,100,53,0,101,28,0,131,3,0,90,29,0, + 71,100,54,0,100,55,0,132,0,0,100,55,0,131,2,0, + 90,30,0,71,100,56,0,100,57,0,132,0,0,100,57,0, + 101,30,0,101,29,0,131,4,0,90,31,0,71,100,58,0, + 100,59,0,132,0,0,100,59,0,101,30,0,101,28,0,131, + 4,0,90,32,0,71,100,60,0,100,61,0,132,0,0,100, + 61,0,131,2,0,90,33,0,71,100,62,0,100,63,0,132, + 0,0,100,63,0,131,2,0,90,34,0,71,100,64,0,100, + 65,0,132,0,0,100,65,0,131,2,0,90,35,0,71,100, + 66,0,100,67,0,132,0,0,100,67,0,131,2,0,90,36, + 0,71,100,68,0,100,69,0,132,0,0,100,69,0,131,2, + 0,90,37,0,71,100,70,0,100,71,0,132,0,0,100,71, + 0,131,2,0,90,38,0,100,72,0,100,73,0,132,0,0, + 90,39,0,101,39,0,90,40,0,71,100,74,0,100,75,0, + 132,0,0,100,75,0,101,34,0,131,3,0,90,41,0,71, + 100,76,0,100,77,0,132,0,0,100,77,0,131,2,0,90, 42,0,100,78,0,100,79,0,132,0,0,90,43,0,100,80, - 0,100,81,0,132,0,0,90,44,0,101,25,0,101,26,0, - 101,40,0,103,3,0,90,45,0,100,82,0,90,46,0,100, - 83,0,100,84,0,132,0,0,90,47,0,100,98,0,100,85, - 0,100,86,0,100,87,0,132,2,0,90,49,0,100,88,0, - 100,89,0,132,0,0,90,50,0,100,90,0,100,91,0,132, - 0,0,90,51,0,105,0,0,105,0,0,103,0,0,100,85, - 0,100,92,0,100,93,0,132,4,0,90,52,0,100,94,0, - 100,95,0,132,0,0,90,53,0,100,96,0,100,97,0,132, - 0,0,90,54,0,100,98,0,83,40,100,0,0,0,117,83, - 1,0,0,67,111,114,101,32,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,32,111,102,32,105,109,112,111,114,116, - 46,10,10,84,104,105,115,32,109,111,100,117,108,101,32,105, - 115,32,78,79,84,32,109,101,97,110,116,32,116,111,32,98, - 101,32,100,105,114,101,99,116,108,121,32,105,109,112,111,114, - 116,101,100,33,32,73,116,32,104,97,115,32,98,101,101,110, - 32,100,101,115,105,103,110,101,100,32,115,117,99,104,10,116, - 104,97,116,32,105,116,32,99,97,110,32,98,101,32,98,111, - 111,116,115,116,114,97,112,112,101,100,32,105,110,116,111,32, - 80,121,116,104,111,110,32,97,115,32,116,104,101,32,105,109, - 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, - 105,109,112,111,114,116,46,32,65,115,10,115,117,99,104,32, - 105,116,32,114,101,113,117,105,114,101,115,32,116,104,101,32, - 105,110,106,101,99,116,105,111,110,32,111,102,32,115,112,101, - 99,105,102,105,99,32,109,111,100,117,108,101,115,32,97,110, - 100,32,97,116,116,114,105,98,117,116,101,115,32,105,110,32, - 111,114,100,101,114,32,116,111,10,119,111,114,107,46,32,79, - 110,101,32,115,104,111,117,108,100,32,117,115,101,32,105,109, - 112,111,114,116,108,105,98,32,97,115,32,116,104,101,32,112, - 117,98,108,105,99,45,102,97,99,105,110,103,32,118,101,114, - 115,105,111,110,32,111,102,32,116,104,105,115,32,109,111,100, - 117,108,101,46,10,10,117,3,0,0,0,119,105,110,117,6, - 0,0,0,99,121,103,119,105,110,117,6,0,0,0,100,97, - 114,119,105,110,99,0,0,0,0,0,0,0,0,1,0,0, - 0,4,0,0,0,67,0,0,0,115,58,0,0,0,116,0, - 0,116,1,0,116,2,0,106,3,0,106,4,0,116,5,0, - 131,2,0,131,1,0,114,42,0,100,1,0,100,2,0,132, - 0,0,125,0,0,110,12,0,100,3,0,100,2,0,132,0, - 0,125,0,0,124,0,0,83,40,4,0,0,0,78,99,0, - 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,83, - 0,0,0,115,13,0,0,0,100,1,0,116,0,0,106,1, - 0,107,6,0,83,40,2,0,0,0,117,53,0,0,0,84, + 0,100,81,0,132,0,0,90,44,0,100,82,0,100,83,0, + 132,0,0,90,45,0,101,26,0,101,27,0,101,41,0,103, + 3,0,90,46,0,100,84,0,90,47,0,100,85,0,100,86, + 0,132,0,0,90,48,0,100,100,0,100,87,0,100,88,0, + 100,89,0,132,2,0,90,50,0,100,90,0,100,91,0,132, + 0,0,90,51,0,100,92,0,100,93,0,132,0,0,90,52, + 0,105,0,0,105,0,0,103,0,0,100,87,0,100,94,0, + 100,95,0,132,4,0,90,53,0,100,96,0,100,97,0,132, + 0,0,90,54,0,100,98,0,100,99,0,132,0,0,90,55, + 0,100,100,0,83,40,102,0,0,0,117,83,1,0,0,67, + 111,114,101,32,105,109,112,108,101,109,101,110,116,97,116,105, + 111,110,32,111,102,32,105,109,112,111,114,116,46,10,10,84, + 104,105,115,32,109,111,100,117,108,101,32,105,115,32,78,79, + 84,32,109,101,97,110,116,32,116,111,32,98,101,32,100,105, + 114,101,99,116,108,121,32,105,109,112,111,114,116,101,100,33, + 32,73,116,32,104,97,115,32,98,101,101,110,32,100,101,115, + 105,103,110,101,100,32,115,117,99,104,10,116,104,97,116,32, + 105,116,32,99,97,110,32,98,101,32,98,111,111,116,115,116, + 114,97,112,112,101,100,32,105,110,116,111,32,80,121,116,104, + 111,110,32,97,115,32,116,104,101,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,111,102,32,105,109,112,111, + 114,116,46,32,65,115,10,115,117,99,104,32,105,116,32,114, + 101,113,117,105,114,101,115,32,116,104,101,32,105,110,106,101, + 99,116,105,111,110,32,111,102,32,115,112,101,99,105,102,105, + 99,32,109,111,100,117,108,101,115,32,97,110,100,32,97,116, + 116,114,105,98,117,116,101,115,32,105,110,32,111,114,100,101, + 114,32,116,111,10,119,111,114,107,46,32,79,110,101,32,115, + 104,111,117,108,100,32,117,115,101,32,105,109,112,111,114,116, + 108,105,98,32,97,115,32,116,104,101,32,112,117,98,108,105, + 99,45,102,97,99,105,110,103,32,118,101,114,115,105,111,110, + 32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,46, + 10,10,117,3,0,0,0,119,105,110,117,6,0,0,0,99, + 121,103,119,105,110,117,6,0,0,0,100,97,114,119,105,110, + 99,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0, + 0,67,0,0,0,115,49,0,0,0,116,0,0,106,1,0, + 106,2,0,116,3,0,131,1,0,114,33,0,100,1,0,100, + 2,0,132,0,0,125,0,0,110,12,0,100,3,0,100,2, + 0,132,0,0,125,0,0,124,0,0,83,40,4,0,0,0, + 78,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,83,0,0,0,115,13,0,0,0,100,1,0,116,0, + 0,106,1,0,107,6,0,83,40,2,0,0,0,117,53,0, + 0,0,84,114,117,101,32,105,102,32,102,105,108,101,110,97, + 109,101,115,32,109,117,115,116,32,98,101,32,99,104,101,99, + 107,101,100,32,99,97,115,101,45,105,110,115,101,110,115,105, + 116,105,118,101,108,121,46,115,12,0,0,0,80,89,84,72, + 79,78,67,65,83,69,79,75,40,2,0,0,0,117,3,0, + 0,0,95,111,115,117,7,0,0,0,101,110,118,105,114,111, + 110,40,0,0,0,0,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,11,0,0,0,95,114,101,108,97,120,95,99,97, + 115,101,27,0,0,0,115,2,0,0,0,0,2,117,37,0, + 0,0,95,109,97,107,101,95,114,101,108,97,120,95,99,97, + 115,101,46,60,108,111,99,97,108,115,62,46,95,114,101,108, + 97,120,95,99,97,115,101,99,0,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0,83,0,0,0,115,4,0,0, + 0,100,1,0,83,40,2,0,0,0,117,53,0,0,0,84, 114,117,101,32,105,102,32,102,105,108,101,110,97,109,101,115, 32,109,117,115,116,32,98,101,32,99,104,101,99,107,101,100, 32,99,97,115,101,45,105,110,115,101,110,115,105,116,105,118, - 101,108,121,46,115,12,0,0,0,80,89,84,72,79,78,67, - 65,83,69,79,75,40,2,0,0,0,117,3,0,0,0,95, - 111,115,117,7,0,0,0,101,110,118,105,114,111,110,40,0, - 0,0,0,40,0,0,0,0,40,0,0,0,0,117,29,0, + 101,108,121,46,70,40,1,0,0,0,117,5,0,0,0,70, + 97,108,115,101,40,0,0,0,0,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,11,0,0,0,95,114,101,108,97,120, + 95,99,97,115,101,31,0,0,0,115,2,0,0,0,0,2, + 40,4,0,0,0,117,3,0,0,0,115,121,115,117,8,0, + 0,0,112,108,97,116,102,111,114,109,117,10,0,0,0,115, + 116,97,114,116,115,119,105,116,104,117,26,0,0,0,67,65, + 83,69,95,73,78,83,69,78,83,73,84,73,86,69,95,80, + 76,65,84,70,79,82,77,83,40,1,0,0,0,117,11,0, + 0,0,95,114,101,108,97,120,95,99,97,115,101,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,16,0,0,0,95,109, + 97,107,101,95,114,101,108,97,120,95,99,97,115,101,25,0, + 0,0,115,8,0,0,0,0,1,18,1,15,4,12,3,117, + 16,0,0,0,95,109,97,107,101,95,114,101,108,97,120,95, + 99,97,115,101,99,1,0,0,0,0,0,0,0,2,0,0, + 0,3,0,0,0,67,0,0,0,115,108,0,0,0,116,0, + 0,124,0,0,131,1,0,125,0,0,103,0,0,125,1,0, + 124,1,0,106,1,0,124,0,0,100,1,0,64,131,1,0, + 1,124,1,0,106,1,0,124,0,0,100,2,0,63,100,1, + 0,64,131,1,0,1,124,1,0,106,1,0,124,0,0,100, + 3,0,63,100,1,0,64,131,1,0,1,124,1,0,106,1, + 0,124,0,0,100,4,0,63,100,1,0,64,131,1,0,1, + 116,2,0,124,1,0,131,1,0,83,40,5,0,0,0,117, + 111,0,0,0,67,111,110,118,101,114,116,32,97,32,51,50, + 45,98,105,116,32,105,110,116,101,103,101,114,32,116,111,32, + 108,105,116,116,108,101,45,101,110,100,105,97,110,46,10,10, + 32,32,32,32,88,88,88,32,84,101,109,112,111,114,97,114, + 121,32,117,110,116,105,108,32,109,97,114,115,104,97,108,39, + 115,32,108,111,110,103,32,102,117,110,99,116,105,111,110,115, + 32,97,114,101,32,101,120,112,111,115,101,100,46,10,10,32, + 32,32,32,105,255,0,0,0,105,8,0,0,0,105,16,0, + 0,0,105,24,0,0,0,40,3,0,0,0,117,3,0,0, + 0,105,110,116,117,6,0,0,0,97,112,112,101,110,100,117, + 9,0,0,0,98,121,116,101,97,114,114,97,121,40,2,0, + 0,0,117,1,0,0,0,120,117,9,0,0,0,105,110,116, + 95,98,121,116,101,115,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,7,0,0,0,95,119,95,108,111,110,103,38,0, + 0,0,115,14,0,0,0,0,6,12,1,6,1,17,1,21, + 1,21,1,21,1,117,7,0,0,0,95,119,95,108,111,110, + 103,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,67,0,0,0,115,68,0,0,0,124,0,0,100,1, + 0,25,125,1,0,124,1,0,124,0,0,100,2,0,25,100, + 3,0,62,79,125,1,0,124,1,0,124,0,0,100,4,0, + 25,100,5,0,62,79,125,1,0,124,1,0,124,0,0,100, + 6,0,25,100,7,0,62,79,125,1,0,124,1,0,83,40, + 8,0,0,0,117,115,0,0,0,67,111,110,118,101,114,116, + 32,52,32,98,121,116,101,115,32,105,110,32,108,105,116,116, + 108,101,45,101,110,100,105,97,110,32,116,111,32,97,110,32, + 105,110,116,101,103,101,114,46,10,10,32,32,32,32,88,88, + 88,32,84,101,109,112,111,114,97,114,121,32,117,110,116,105, + 108,32,109,97,114,115,104,97,108,39,115,32,108,111,110,103, + 32,102,117,110,99,116,105,111,110,32,97,114,101,32,101,120, + 112,111,115,101,100,46,10,10,32,32,32,32,105,0,0,0, + 0,105,1,0,0,0,105,8,0,0,0,105,2,0,0,0, + 105,16,0,0,0,105,3,0,0,0,105,24,0,0,0,40, + 0,0,0,0,40,2,0,0,0,117,9,0,0,0,105,110, + 116,95,98,121,116,101,115,117,1,0,0,0,120,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,7,0,0,0,95,114, + 95,108,111,110,103,54,0,0,0,115,10,0,0,0,0,6, + 10,1,18,1,18,1,18,1,117,7,0,0,0,95,114,95, + 108,111,110,103,99,0,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,71,0,0,0,115,26,0,0,0,116,0, + 0,106,1,0,100,1,0,100,2,0,132,0,0,124,0,0, + 68,131,1,0,131,1,0,83,40,3,0,0,0,117,29,0, + 0,0,82,101,112,108,97,99,101,109,101,110,116,32,102,111, + 114,32,111,115,46,112,97,116,104,46,106,111,105,110,46,99, + 1,0,0,0,0,0,0,0,2,0,0,0,5,0,0,0, + 115,0,0,0,115,65,0,0,0,124,0,0,93,55,0,125, + 1,0,124,1,0,114,3,0,124,1,0,106,0,0,116,1, + 0,131,1,0,114,53,0,124,1,0,100,0,0,116,2,0, + 116,1,0,131,1,0,11,133,2,0,25,110,3,0,124,1, + 0,86,1,113,3,0,100,0,0,83,40,1,0,0,0,78, + 40,3,0,0,0,117,8,0,0,0,101,110,100,115,119,105, + 116,104,117,8,0,0,0,112,97,116,104,95,115,101,112,117, + 3,0,0,0,108,101,110,40,2,0,0,0,117,2,0,0, + 0,46,48,117,1,0,0,0,120,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,9,0,0,0,60,103,101,110,101,120, + 112,114,62,71,0,0,0,115,2,0,0,0,6,1,117,29, + 0,0,0,95,112,97,116,104,95,106,111,105,110,46,60,108, + 111,99,97,108,115,62,46,60,103,101,110,101,120,112,114,62, + 40,2,0,0,0,117,8,0,0,0,112,97,116,104,95,115, + 101,112,117,4,0,0,0,106,111,105,110,40,1,0,0,0, + 117,4,0,0,0,97,114,103,115,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,10,0,0,0,95,112,97,116,104,95, + 106,111,105,110,69,0,0,0,115,4,0,0,0,0,2,15, + 1,117,10,0,0,0,95,112,97,116,104,95,106,111,105,110, + 99,1,0,0,0,0,0,0,0,1,0,0,0,11,0,0, + 0,67,0,0,0,115,50,0,0,0,121,17,0,116,0,0, + 106,1,0,124,0,0,131,1,0,1,87,110,22,0,4,116, + 2,0,107,10,0,114,41,0,1,1,1,100,2,0,83,89, + 110,5,0,88,100,3,0,83,100,1,0,83,40,4,0,0, + 0,117,31,0,0,0,82,101,112,108,97,99,101,109,101,110, + 116,32,102,111,114,32,111,115,46,112,97,116,104,46,101,120, + 105,115,116,115,46,78,70,84,40,5,0,0,0,117,3,0, + 0,0,95,111,115,117,4,0,0,0,115,116,97,116,117,7, + 0,0,0,79,83,69,114,114,111,114,117,5,0,0,0,70, + 97,108,115,101,117,4,0,0,0,84,114,117,101,40,1,0, + 0,0,117,4,0,0,0,112,97,116,104,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,12,0,0,0,95,112,97,116, + 104,95,101,120,105,115,116,115,75,0,0,0,115,10,0,0, + 0,0,2,3,1,17,1,13,1,9,2,117,12,0,0,0, + 95,112,97,116,104,95,101,120,105,115,116,115,99,2,0,0, + 0,0,0,0,0,3,0,0,0,11,0,0,0,67,0,0, + 0,115,61,0,0,0,121,19,0,116,0,0,106,1,0,124, + 0,0,131,1,0,125,2,0,87,110,22,0,4,116,2,0, + 107,10,0,114,43,0,1,1,1,100,2,0,83,89,110,1, + 0,88,124,2,0,106,4,0,100,1,0,64,124,1,0,107, + 2,0,83,40,3,0,0,0,117,49,0,0,0,84,101,115, + 116,32,119,104,101,116,104,101,114,32,116,104,101,32,112,97, + 116,104,32,105,115,32,116,104,101,32,115,112,101,99,105,102, + 105,101,100,32,109,111,100,101,32,116,121,112,101,46,105,0, + 240,0,0,70,40,5,0,0,0,117,3,0,0,0,95,111, + 115,117,4,0,0,0,115,116,97,116,117,7,0,0,0,79, + 83,69,114,114,111,114,117,5,0,0,0,70,97,108,115,101, + 117,7,0,0,0,115,116,95,109,111,100,101,40,3,0,0, + 0,117,4,0,0,0,112,97,116,104,117,4,0,0,0,109, + 111,100,101,117,9,0,0,0,115,116,97,116,95,105,110,102, + 111,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,18,0, + 0,0,95,112,97,116,104,95,105,115,95,109,111,100,101,95, + 116,121,112,101,85,0,0,0,115,10,0,0,0,0,2,3, + 1,19,1,13,1,9,1,117,18,0,0,0,95,112,97,116, + 104,95,105,115,95,109,111,100,101,95,116,121,112,101,99,1, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,115,13,0,0,0,116,0,0,124,0,0,100,1, + 0,131,2,0,83,40,2,0,0,0,117,31,0,0,0,82, + 101,112,108,97,99,101,109,101,110,116,32,102,111,114,32,111, + 115,46,112,97,116,104,46,105,115,102,105,108,101,46,105,0, + 128,0,0,40,1,0,0,0,117,18,0,0,0,95,112,97, + 116,104,95,105,115,95,109,111,100,101,95,116,121,112,101,40, + 1,0,0,0,117,4,0,0,0,112,97,116,104,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,12,0,0,0,95,112, + 97,116,104,95,105,115,102,105,108,101,95,0,0,0,115,2, + 0,0,0,0,2,117,12,0,0,0,95,112,97,116,104,95, + 105,115,102,105,108,101,99,1,0,0,0,0,0,0,0,1, + 0,0,0,3,0,0,0,67,0,0,0,115,34,0,0,0, + 124,0,0,115,21,0,116,0,0,106,1,0,131,0,0,125, + 0,0,110,0,0,116,2,0,124,0,0,100,1,0,131,2, + 0,83,40,2,0,0,0,117,30,0,0,0,82,101,112,108, + 97,99,101,109,101,110,116,32,102,111,114,32,111,115,46,112, + 97,116,104,46,105,115,100,105,114,46,105,0,64,0,0,40, + 3,0,0,0,117,3,0,0,0,95,111,115,117,6,0,0, + 0,103,101,116,99,119,100,117,18,0,0,0,95,112,97,116, + 104,95,105,115,95,109,111,100,101,95,116,121,112,101,40,1, + 0,0,0,117,4,0,0,0,112,97,116,104,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,11,0,0,0,95,112,97, + 116,104,95,105,115,100,105,114,101,0,0,0,115,6,0,0, + 0,0,2,6,1,15,1,117,11,0,0,0,95,112,97,116, + 104,95,105,115,100,105,114,99,2,0,0,0,0,0,0,0, + 3,0,0,0,5,0,0,0,67,0,0,0,115,75,0,0, + 0,120,68,0,116,0,0,124,1,0,131,1,0,68,93,42, + 0,125,2,0,124,0,0,106,1,0,124,2,0,131,1,0, + 114,13,0,124,0,0,100,1,0,116,2,0,124,2,0,131, + 1,0,11,133,2,0,25,83,113,13,0,87,116,3,0,100, + 2,0,131,1,0,130,1,0,100,1,0,83,40,3,0,0, + 0,117,38,0,0,0,82,101,112,108,97,99,101,109,101,110, + 116,32,102,111,114,32,111,115,46,112,97,116,104,46,115,112, + 108,105,116,101,120,116,40,41,91,48,93,46,78,117,33,0, + 0,0,112,97,116,104,32,105,115,32,110,111,116,32,111,102, + 32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,116, + 121,112,101,40,4,0,0,0,117,12,0,0,0,95,115,117, + 102,102,105,120,95,108,105,115,116,117,8,0,0,0,101,110, + 100,115,119,105,116,104,117,3,0,0,0,108,101,110,117,10, + 0,0,0,86,97,108,117,101,69,114,114,111,114,40,3,0, + 0,0,117,4,0,0,0,112,97,116,104,117,8,0,0,0, + 101,120,116,95,116,121,112,101,117,6,0,0,0,115,117,102, + 102,105,120,40,0,0,0,0,40,0,0,0,0,117,29,0, 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 11,0,0,0,95,114,101,108,97,120,95,99,97,115,101,27, - 0,0,0,115,2,0,0,0,0,2,117,37,0,0,0,95, - 109,97,107,101,95,114,101,108,97,120,95,99,97,115,101,46, - 60,108,111,99,97,108,115,62,46,95,114,101,108,97,120,95, - 99,97,115,101,99,0,0,0,0,0,0,0,0,0,0,0, - 0,1,0,0,0,83,0,0,0,115,4,0,0,0,100,1, - 0,83,40,2,0,0,0,117,53,0,0,0,84,114,117,101, - 32,105,102,32,102,105,108,101,110,97,109,101,115,32,109,117, - 115,116,32,98,101,32,99,104,101,99,107,101,100,32,99,97, - 115,101,45,105,110,115,101,110,115,105,116,105,118,101,108,121, - 46,70,40,1,0,0,0,117,5,0,0,0,70,97,108,115, - 101,40,0,0,0,0,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,11,0,0,0,95,114,101,108,97,120,95,99,97, - 115,101,31,0,0,0,115,2,0,0,0,0,2,40,6,0, - 0,0,117,3,0,0,0,97,110,121,117,3,0,0,0,109, - 97,112,117,3,0,0,0,115,121,115,117,8,0,0,0,112, - 108,97,116,102,111,114,109,117,10,0,0,0,115,116,97,114, - 116,115,119,105,116,104,117,26,0,0,0,67,65,83,69,95, - 73,78,83,69,78,83,73,84,73,86,69,95,80,76,65,84, - 70,79,82,77,83,40,1,0,0,0,117,11,0,0,0,95, - 114,101,108,97,120,95,99,97,115,101,40,0,0,0,0,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,16,0,0,0,95,109,97,107,101, - 95,114,101,108,97,120,95,99,97,115,101,25,0,0,0,115, - 8,0,0,0,0,1,27,1,15,4,12,3,117,16,0,0, - 0,95,109,97,107,101,95,114,101,108,97,120,95,99,97,115, - 101,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,67,0,0,0,115,108,0,0,0,116,0,0,124,0, - 0,131,1,0,125,0,0,103,0,0,125,1,0,124,1,0, - 106,1,0,124,0,0,100,1,0,64,131,1,0,1,124,1, - 0,106,1,0,124,0,0,100,2,0,63,100,1,0,64,131, - 1,0,1,124,1,0,106,1,0,124,0,0,100,3,0,63, - 100,1,0,64,131,1,0,1,124,1,0,106,1,0,124,0, - 0,100,4,0,63,100,1,0,64,131,1,0,1,116,2,0, - 124,1,0,131,1,0,83,40,5,0,0,0,117,111,0,0, - 0,67,111,110,118,101,114,116,32,97,32,51,50,45,98,105, - 116,32,105,110,116,101,103,101,114,32,116,111,32,108,105,116, - 116,108,101,45,101,110,100,105,97,110,46,10,10,32,32,32, - 32,88,88,88,32,84,101,109,112,111,114,97,114,121,32,117, - 110,116,105,108,32,109,97,114,115,104,97,108,39,115,32,108, - 111,110,103,32,102,117,110,99,116,105,111,110,115,32,97,114, - 101,32,101,120,112,111,115,101,100,46,10,10,32,32,32,32, - 105,255,0,0,0,105,8,0,0,0,105,16,0,0,0,105, - 24,0,0,0,40,3,0,0,0,117,3,0,0,0,105,110, - 116,117,6,0,0,0,97,112,112,101,110,100,117,9,0,0, - 0,98,121,116,101,97,114,114,97,121,40,2,0,0,0,117, - 1,0,0,0,120,117,9,0,0,0,105,110,116,95,98,121, - 116,101,115,40,0,0,0,0,40,0,0,0,0,117,29,0, - 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, - 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 7,0,0,0,95,119,95,108,111,110,103,38,0,0,0,115, - 14,0,0,0,0,6,12,1,6,1,17,1,21,1,21,1, - 21,1,117,7,0,0,0,95,119,95,108,111,110,103,99,1, - 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, - 0,0,0,115,68,0,0,0,124,0,0,100,1,0,25,125, - 1,0,124,1,0,124,0,0,100,2,0,25,100,3,0,62, - 79,125,1,0,124,1,0,124,0,0,100,4,0,25,100,5, - 0,62,79,125,1,0,124,1,0,124,0,0,100,6,0,25, - 100,7,0,62,79,125,1,0,124,1,0,83,40,8,0,0, - 0,117,115,0,0,0,67,111,110,118,101,114,116,32,52,32, - 98,121,116,101,115,32,105,110,32,108,105,116,116,108,101,45, - 101,110,100,105,97,110,32,116,111,32,97,110,32,105,110,116, - 101,103,101,114,46,10,10,32,32,32,32,88,88,88,32,84, - 101,109,112,111,114,97,114,121,32,117,110,116,105,108,32,109, - 97,114,115,104,97,108,39,115,32,108,111,110,103,32,102,117, - 110,99,116,105,111,110,32,97,114,101,32,101,120,112,111,115, - 101,100,46,10,10,32,32,32,32,105,0,0,0,0,105,1, - 0,0,0,105,8,0,0,0,105,2,0,0,0,105,16,0, - 0,0,105,3,0,0,0,105,24,0,0,0,40,0,0,0, - 0,40,2,0,0,0,117,9,0,0,0,105,110,116,95,98, - 121,116,101,115,117,1,0,0,0,120,40,0,0,0,0,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,7,0,0,0,95,114,95,108,111, - 110,103,54,0,0,0,115,10,0,0,0,0,6,10,1,18, - 1,18,1,18,1,117,7,0,0,0,95,114,95,108,111,110, - 103,99,0,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,71,0,0,0,115,26,0,0,0,116,0,0,106,1, - 0,100,1,0,100,2,0,132,0,0,124,0,0,68,131,1, - 0,131,1,0,83,40,3,0,0,0,117,29,0,0,0,82, - 101,112,108,97,99,101,109,101,110,116,32,102,111,114,32,111, - 115,46,112,97,116,104,46,106,111,105,110,46,99,1,0,0, - 0,0,0,0,0,2,0,0,0,5,0,0,0,115,0,0, - 0,115,65,0,0,0,124,0,0,93,55,0,125,1,0,124, - 1,0,114,3,0,124,1,0,106,0,0,116,1,0,131,1, - 0,114,53,0,124,1,0,100,0,0,116,2,0,116,1,0, - 131,1,0,11,133,2,0,25,110,3,0,124,1,0,86,1, - 113,3,0,100,0,0,83,40,1,0,0,0,78,40,3,0, - 0,0,117,8,0,0,0,101,110,100,115,119,105,116,104,117, - 8,0,0,0,112,97,116,104,95,115,101,112,117,3,0,0, - 0,108,101,110,40,2,0,0,0,117,2,0,0,0,46,48, - 117,1,0,0,0,120,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,9,0,0,0,60,103,101,110,101,120,112,114,62, - 71,0,0,0,115,2,0,0,0,6,1,117,29,0,0,0, - 95,112,97,116,104,95,106,111,105,110,46,60,108,111,99,97, - 108,115,62,46,60,103,101,110,101,120,112,114,62,40,2,0, - 0,0,117,8,0,0,0,112,97,116,104,95,115,101,112,117, - 4,0,0,0,106,111,105,110,40,1,0,0,0,117,4,0, - 0,0,97,114,103,115,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,10,0,0,0,95,112,97,116,104,95,106,111,105, - 110,69,0,0,0,115,4,0,0,0,0,2,15,1,117,10, - 0,0,0,95,112,97,116,104,95,106,111,105,110,99,1,0, - 0,0,0,0,0,0,1,0,0,0,11,0,0,0,67,0, - 0,0,115,50,0,0,0,121,17,0,116,0,0,106,1,0, - 124,0,0,131,1,0,1,87,110,22,0,4,116,2,0,107, - 10,0,114,41,0,1,1,1,100,2,0,83,89,110,5,0, - 88,100,3,0,83,100,1,0,83,40,4,0,0,0,117,31, - 0,0,0,82,101,112,108,97,99,101,109,101,110,116,32,102, - 111,114,32,111,115,46,112,97,116,104,46,101,120,105,115,116, - 115,46,78,70,84,40,5,0,0,0,117,3,0,0,0,95, - 111,115,117,4,0,0,0,115,116,97,116,117,7,0,0,0, - 79,83,69,114,114,111,114,117,5,0,0,0,70,97,108,115, - 101,117,4,0,0,0,84,114,117,101,40,1,0,0,0,117, + 17,0,0,0,95,112,97,116,104,95,119,105,116,104,111,117, + 116,95,101,120,116,108,0,0,0,115,8,0,0,0,0,2, + 19,1,15,1,25,2,117,17,0,0,0,95,112,97,116,104, + 95,119,105,116,104,111,117,116,95,101,120,116,99,1,0,0, + 0,0,0,0,0,1,0,0,0,11,0,0,0,67,0,0, + 0,115,101,0,0,0,124,0,0,115,21,0,116,0,0,106, + 1,0,131,0,0,125,0,0,110,0,0,121,17,0,116,0, + 0,106,2,0,124,0,0,131,1,0,83,87,110,56,0,4, + 116,3,0,107,10,0,114,96,0,1,1,1,124,0,0,106, + 4,0,100,1,0,131,1,0,114,73,0,124,0,0,83,116, + 5,0,116,0,0,106,1,0,131,0,0,124,0,0,131,2, + 0,83,89,110,1,0,88,100,2,0,83,40,3,0,0,0, + 117,32,0,0,0,82,101,112,108,97,99,101,109,101,110,116, + 32,102,111,114,32,111,115,46,112,97,116,104,46,97,98,115, + 112,97,116,104,46,117,1,0,0,0,47,78,40,6,0,0, + 0,117,3,0,0,0,95,111,115,117,6,0,0,0,103,101, + 116,99,119,100,117,16,0,0,0,95,103,101,116,102,117,108, + 108,112,97,116,104,110,97,109,101,117,14,0,0,0,65,116, + 116,114,105,98,117,116,101,69,114,114,111,114,117,10,0,0, + 0,115,116,97,114,116,115,119,105,116,104,117,10,0,0,0, + 95,112,97,116,104,95,106,111,105,110,40,1,0,0,0,117, 4,0,0,0,112,97,116,104,40,0,0,0,0,40,0,0, 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,12,0,0,0,95,112,97,116,104,95,101, - 120,105,115,116,115,75,0,0,0,115,10,0,0,0,0,2, - 3,1,17,1,13,1,9,2,117,12,0,0,0,95,112,97, - 116,104,95,101,120,105,115,116,115,99,2,0,0,0,0,0, - 0,0,3,0,0,0,11,0,0,0,67,0,0,0,115,61, - 0,0,0,121,19,0,116,0,0,106,1,0,124,0,0,131, - 1,0,125,2,0,87,110,22,0,4,116,2,0,107,10,0, - 114,43,0,1,1,1,100,2,0,83,89,110,1,0,88,124, - 2,0,106,4,0,100,1,0,64,124,1,0,107,2,0,83, - 40,3,0,0,0,117,49,0,0,0,84,101,115,116,32,119, - 104,101,116,104,101,114,32,116,104,101,32,112,97,116,104,32, - 105,115,32,116,104,101,32,115,112,101,99,105,102,105,101,100, - 32,109,111,100,101,32,116,121,112,101,46,105,0,240,0,0, - 70,40,5,0,0,0,117,3,0,0,0,95,111,115,117,4, - 0,0,0,115,116,97,116,117,7,0,0,0,79,83,69,114, - 114,111,114,117,5,0,0,0,70,97,108,115,101,117,7,0, - 0,0,115,116,95,109,111,100,101,40,3,0,0,0,117,4, - 0,0,0,112,97,116,104,117,4,0,0,0,109,111,100,101, - 117,9,0,0,0,115,116,97,116,95,105,110,102,111,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,18,0,0,0,95, - 112,97,116,104,95,105,115,95,109,111,100,101,95,116,121,112, - 101,85,0,0,0,115,10,0,0,0,0,2,3,1,19,1, - 13,1,9,1,117,18,0,0,0,95,112,97,116,104,95,105, - 115,95,109,111,100,101,95,116,121,112,101,99,1,0,0,0, - 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, - 115,13,0,0,0,116,0,0,124,0,0,100,1,0,131,2, - 0,83,40,2,0,0,0,117,31,0,0,0,82,101,112,108, - 97,99,101,109,101,110,116,32,102,111,114,32,111,115,46,112, - 97,116,104,46,105,115,102,105,108,101,46,105,0,128,0,0, - 40,1,0,0,0,117,18,0,0,0,95,112,97,116,104,95, - 105,115,95,109,111,100,101,95,116,121,112,101,40,1,0,0, - 0,117,4,0,0,0,112,97,116,104,40,0,0,0,0,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,12,0,0,0,95,112,97,116,104, - 95,105,115,102,105,108,101,95,0,0,0,115,2,0,0,0, - 0,2,117,12,0,0,0,95,112,97,116,104,95,105,115,102, - 105,108,101,99,1,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,115,34,0,0,0,124,0,0, - 115,21,0,116,0,0,106,1,0,131,0,0,125,0,0,110, - 0,0,116,2,0,124,0,0,100,1,0,131,2,0,83,40, - 2,0,0,0,117,30,0,0,0,82,101,112,108,97,99,101, - 109,101,110,116,32,102,111,114,32,111,115,46,112,97,116,104, - 46,105,115,100,105,114,46,105,0,64,0,0,40,3,0,0, - 0,117,3,0,0,0,95,111,115,117,6,0,0,0,103,101, - 116,99,119,100,117,18,0,0,0,95,112,97,116,104,95,105, - 115,95,109,111,100,101,95,116,121,112,101,40,1,0,0,0, - 117,4,0,0,0,112,97,116,104,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,11,0,0,0,95,112,97,116,104,95, - 105,115,100,105,114,101,0,0,0,115,6,0,0,0,0,2, - 6,1,15,1,117,11,0,0,0,95,112,97,116,104,95,105, - 115,100,105,114,99,2,0,0,0,0,0,0,0,3,0,0, - 0,5,0,0,0,67,0,0,0,115,75,0,0,0,120,68, - 0,116,0,0,124,1,0,131,1,0,68,93,42,0,125,2, - 0,124,0,0,106,1,0,124,2,0,131,1,0,114,13,0, - 124,0,0,100,1,0,116,2,0,124,2,0,131,1,0,11, - 133,2,0,25,83,113,13,0,87,116,3,0,100,2,0,131, - 1,0,130,1,0,100,1,0,83,40,3,0,0,0,117,38, - 0,0,0,82,101,112,108,97,99,101,109,101,110,116,32,102, - 111,114,32,111,115,46,112,97,116,104,46,115,112,108,105,116, - 101,120,116,40,41,91,48,93,46,78,117,33,0,0,0,112, - 97,116,104,32,105,115,32,110,111,116,32,111,102,32,116,104, - 101,32,115,112,101,99,105,102,105,101,100,32,116,121,112,101, - 40,4,0,0,0,117,12,0,0,0,95,115,117,102,102,105, - 120,95,108,105,115,116,117,8,0,0,0,101,110,100,115,119, - 105,116,104,117,3,0,0,0,108,101,110,117,10,0,0,0, - 86,97,108,117,101,69,114,114,111,114,40,3,0,0,0,117, - 4,0,0,0,112,97,116,104,117,8,0,0,0,101,120,116, - 95,116,121,112,101,117,6,0,0,0,115,117,102,102,105,120, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,17,0,0, - 0,95,112,97,116,104,95,119,105,116,104,111,117,116,95,101, - 120,116,108,0,0,0,115,8,0,0,0,0,2,19,1,15, - 1,25,2,117,17,0,0,0,95,112,97,116,104,95,119,105, - 116,104,111,117,116,95,101,120,116,99,1,0,0,0,0,0, - 0,0,1,0,0,0,11,0,0,0,67,0,0,0,115,101, - 0,0,0,124,0,0,115,21,0,116,0,0,106,1,0,131, - 0,0,125,0,0,110,0,0,121,17,0,116,0,0,106,2, - 0,124,0,0,131,1,0,83,87,110,56,0,4,116,3,0, - 107,10,0,114,96,0,1,1,1,124,0,0,106,4,0,100, - 1,0,131,1,0,114,73,0,124,0,0,83,116,5,0,116, - 0,0,106,1,0,131,0,0,124,0,0,131,2,0,83,89, - 110,1,0,88,100,2,0,83,40,3,0,0,0,117,32,0, - 0,0,82,101,112,108,97,99,101,109,101,110,116,32,102,111, - 114,32,111,115,46,112,97,116,104,46,97,98,115,112,97,116, - 104,46,117,1,0,0,0,47,78,40,6,0,0,0,117,3, - 0,0,0,95,111,115,117,6,0,0,0,103,101,116,99,119, - 100,117,16,0,0,0,95,103,101,116,102,117,108,108,112,97, - 116,104,110,97,109,101,117,14,0,0,0,65,116,116,114,105, - 98,117,116,101,69,114,114,111,114,117,10,0,0,0,115,116, - 97,114,116,115,119,105,116,104,117,10,0,0,0,95,112,97, - 116,104,95,106,111,105,110,40,1,0,0,0,117,4,0,0, - 0,112,97,116,104,40,0,0,0,0,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,14,0,0,0,95,112,97,116,104,95,97,98,115,111, - 108,117,116,101,117,0,0,0,115,16,0,0,0,0,2,6, - 1,15,1,3,1,17,1,13,1,15,1,4,2,117,14,0, - 0,0,95,112,97,116,104,95,97,98,115,111,108,117,116,101, - 99,2,0,0,0,0,0,0,0,5,0,0,0,17,0,0, - 0,67,0,0,0,115,188,0,0,0,100,1,0,106,0,0, - 124,0,0,116,1,0,124,0,0,131,1,0,131,2,0,125, - 2,0,116,2,0,106,3,0,124,2,0,116,2,0,106,4, - 0,116,2,0,106,5,0,66,116,2,0,106,6,0,66,100, - 2,0,131,3,0,125,3,0,121,60,0,116,7,0,106,8, - 0,124,3,0,100,3,0,131,2,0,143,20,0,125,4,0, - 124,4,0,106,9,0,124,1,0,131,1,0,1,87,100,4, - 0,81,88,116,2,0,106,10,0,124,2,0,124,0,0,131, - 2,0,1,87,110,59,0,4,116,11,0,107,10,0,114,183, - 0,1,1,1,121,17,0,116,2,0,106,12,0,124,2,0, - 131,1,0,1,87,110,18,0,4,116,11,0,107,10,0,114, - 175,0,1,1,1,89,110,1,0,88,130,0,0,89,110,1, - 0,88,100,4,0,83,40,5,0,0,0,117,162,0,0,0, - 66,101,115,116,45,101,102,102,111,114,116,32,102,117,110,99, - 116,105,111,110,32,116,111,32,119,114,105,116,101,32,100,97, - 116,97,32,116,111,32,97,32,112,97,116,104,32,97,116,111, - 109,105,99,97,108,108,121,46,10,32,32,32,32,66,101,32, - 112,114,101,112,97,114,101,100,32,116,111,32,104,97,110,100, - 108,101,32,97,32,70,105,108,101,69,120,105,115,116,115,69, - 114,114,111,114,32,105,102,32,99,111,110,99,117,114,114,101, - 110,116,32,119,114,105,116,105,110,103,32,111,102,32,116,104, - 101,10,32,32,32,32,116,101,109,112,111,114,97,114,121,32, - 102,105,108,101,32,105,115,32,97,116,116,101,109,112,116,101, - 100,46,117,5,0,0,0,123,125,46,123,125,105,182,1,0, - 0,117,2,0,0,0,119,98,78,40,13,0,0,0,117,6, - 0,0,0,102,111,114,109,97,116,117,2,0,0,0,105,100, - 117,3,0,0,0,95,111,115,117,4,0,0,0,111,112,101, - 110,117,6,0,0,0,79,95,69,88,67,76,117,7,0,0, - 0,79,95,67,82,69,65,84,117,8,0,0,0,79,95,87, - 82,79,78,76,89,117,3,0,0,0,95,105,111,117,6,0, - 0,0,70,105,108,101,73,79,117,5,0,0,0,119,114,105, - 116,101,117,7,0,0,0,114,101,112,108,97,99,101,117,7, - 0,0,0,79,83,69,114,114,111,114,117,6,0,0,0,117, - 110,108,105,110,107,40,5,0,0,0,117,4,0,0,0,112, - 97,116,104,117,4,0,0,0,100,97,116,97,117,8,0,0, - 0,112,97,116,104,95,116,109,112,117,2,0,0,0,102,100, - 117,4,0,0,0,102,105,108,101,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,13,0,0,0,95,119,114,105,116,101, - 95,97,116,111,109,105,99,130,0,0,0,115,24,0,0,0, - 0,5,24,1,38,1,3,3,21,1,19,1,20,1,13,1, - 3,1,17,1,13,1,5,1,117,13,0,0,0,95,119,114, - 105,116,101,95,97,116,111,109,105,99,99,2,0,0,0,0, - 0,0,0,3,0,0,0,7,0,0,0,67,0,0,0,115, - 95,0,0,0,120,69,0,100,1,0,100,2,0,100,3,0, - 100,4,0,103,4,0,68,93,49,0,125,2,0,116,0,0, - 124,1,0,124,2,0,131,2,0,114,19,0,116,1,0,124, - 0,0,124,2,0,116,2,0,124,1,0,124,2,0,131,2, - 0,131,3,0,1,113,19,0,113,19,0,87,124,0,0,106, - 3,0,106,4,0,124,1,0,106,3,0,131,1,0,1,100, - 5,0,83,40,6,0,0,0,117,38,0,0,0,83,105,109, - 112,108,101,32,115,117,98,115,116,105,116,117,116,101,32,102, - 111,114,32,102,117,110,99,116,111,111,108,115,46,119,114,97, - 112,115,46,117,10,0,0,0,95,95,109,111,100,117,108,101, - 95,95,117,8,0,0,0,95,95,110,97,109,101,95,95,117, - 12,0,0,0,95,95,113,117,97,108,110,97,109,101,95,95, - 117,7,0,0,0,95,95,100,111,99,95,95,78,40,5,0, - 0,0,117,7,0,0,0,104,97,115,97,116,116,114,117,7, - 0,0,0,115,101,116,97,116,116,114,117,7,0,0,0,103, - 101,116,97,116,116,114,117,8,0,0,0,95,95,100,105,99, - 116,95,95,117,6,0,0,0,117,112,100,97,116,101,40,3, - 0,0,0,117,3,0,0,0,110,101,119,117,3,0,0,0, - 111,108,100,117,7,0,0,0,114,101,112,108,97,99,101,40, - 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,5,0,0,0, - 95,119,114,97,112,151,0,0,0,115,8,0,0,0,0,2, - 25,1,15,1,32,1,117,5,0,0,0,95,119,114,97,112, - 99,1,0,0,0,0,0,0,0,2,0,0,0,5,0,0, - 0,71,0,0,0,115,92,0,0,0,116,0,0,106,1,0, - 106,2,0,114,88,0,124,0,0,106,3,0,100,1,0,131, - 1,0,12,114,57,0,124,0,0,106,3,0,100,2,0,131, - 1,0,12,114,57,0,100,3,0,124,0,0,23,125,0,0, - 110,0,0,116,4,0,124,0,0,106,5,0,124,1,0,140, - 0,0,100,4,0,116,0,0,106,6,0,131,1,1,1,110, - 0,0,100,5,0,83,40,6,0,0,0,117,61,0,0,0, - 80,114,105,110,116,32,116,104,101,32,109,101,115,115,97,103, - 101,32,116,111,32,115,116,100,101,114,114,32,105,102,32,45, - 118,47,80,89,84,72,79,78,86,69,82,66,79,83,69,32, - 105,115,32,116,117,114,110,101,100,32,111,110,46,117,1,0, - 0,0,35,117,7,0,0,0,105,109,112,111,114,116,32,117, - 2,0,0,0,35,32,117,4,0,0,0,102,105,108,101,78, - 40,7,0,0,0,117,3,0,0,0,115,121,115,117,5,0, - 0,0,102,108,97,103,115,117,7,0,0,0,118,101,114,98, - 111,115,101,117,10,0,0,0,115,116,97,114,116,115,119,105, - 116,104,117,5,0,0,0,112,114,105,110,116,117,6,0,0, - 0,102,111,114,109,97,116,117,6,0,0,0,115,116,100,101, - 114,114,40,2,0,0,0,117,7,0,0,0,109,101,115,115, - 97,103,101,117,4,0,0,0,97,114,103,115,40,0,0,0, + 114,97,112,62,117,14,0,0,0,95,112,97,116,104,95,97, + 98,115,111,108,117,116,101,117,0,0,0,115,16,0,0,0, + 0,2,6,1,15,1,3,1,17,1,13,1,15,1,4,2, + 117,14,0,0,0,95,112,97,116,104,95,97,98,115,111,108, + 117,116,101,99,2,0,0,0,0,0,0,0,5,0,0,0, + 17,0,0,0,67,0,0,0,115,188,0,0,0,100,1,0, + 106,0,0,124,0,0,116,1,0,124,0,0,131,1,0,131, + 2,0,125,2,0,116,2,0,106,3,0,124,2,0,116,2, + 0,106,4,0,116,2,0,106,5,0,66,116,2,0,106,6, + 0,66,100,2,0,131,3,0,125,3,0,121,60,0,116,7, + 0,106,8,0,124,3,0,100,3,0,131,2,0,143,20,0, + 125,4,0,124,4,0,106,9,0,124,1,0,131,1,0,1, + 87,100,4,0,81,88,116,2,0,106,10,0,124,2,0,124, + 0,0,131,2,0,1,87,110,59,0,4,116,11,0,107,10, + 0,114,183,0,1,1,1,121,17,0,116,2,0,106,12,0, + 124,2,0,131,1,0,1,87,110,18,0,4,116,11,0,107, + 10,0,114,175,0,1,1,1,89,110,1,0,88,130,0,0, + 89,110,1,0,88,100,4,0,83,40,5,0,0,0,117,162, + 0,0,0,66,101,115,116,45,101,102,102,111,114,116,32,102, + 117,110,99,116,105,111,110,32,116,111,32,119,114,105,116,101, + 32,100,97,116,97,32,116,111,32,97,32,112,97,116,104,32, + 97,116,111,109,105,99,97,108,108,121,46,10,32,32,32,32, + 66,101,32,112,114,101,112,97,114,101,100,32,116,111,32,104, + 97,110,100,108,101,32,97,32,70,105,108,101,69,120,105,115, + 116,115,69,114,114,111,114,32,105,102,32,99,111,110,99,117, + 114,114,101,110,116,32,119,114,105,116,105,110,103,32,111,102, + 32,116,104,101,10,32,32,32,32,116,101,109,112,111,114,97, + 114,121,32,102,105,108,101,32,105,115,32,97,116,116,101,109, + 112,116,101,100,46,117,5,0,0,0,123,125,46,123,125,105, + 182,1,0,0,117,2,0,0,0,119,98,78,40,13,0,0, + 0,117,6,0,0,0,102,111,114,109,97,116,117,2,0,0, + 0,105,100,117,3,0,0,0,95,111,115,117,4,0,0,0, + 111,112,101,110,117,6,0,0,0,79,95,69,88,67,76,117, + 7,0,0,0,79,95,67,82,69,65,84,117,8,0,0,0, + 79,95,87,82,79,78,76,89,117,3,0,0,0,95,105,111, + 117,6,0,0,0,70,105,108,101,73,79,117,5,0,0,0, + 119,114,105,116,101,117,7,0,0,0,114,101,112,108,97,99, + 101,117,7,0,0,0,79,83,69,114,114,111,114,117,6,0, + 0,0,117,110,108,105,110,107,40,5,0,0,0,117,4,0, + 0,0,112,97,116,104,117,4,0,0,0,100,97,116,97,117, + 8,0,0,0,112,97,116,104,95,116,109,112,117,2,0,0, + 0,102,100,117,4,0,0,0,102,105,108,101,40,0,0,0, 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, - 111,116,115,116,114,97,112,62,117,15,0,0,0,118,101,114, - 98,111,115,101,95,109,101,115,115,97,103,101,163,0,0,0, - 115,8,0,0,0,0,2,12,1,32,1,13,1,117,15,0, - 0,0,118,101,114,98,111,115,101,95,109,101,115,115,97,103, - 101,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,3,0,0,0,115,35,0,0,0,135,0,0,102,1, - 0,100,1,0,100,2,0,134,0,0,125,1,0,116,0,0, - 124,1,0,136,0,0,131,2,0,1,124,1,0,83,40,3, - 0,0,0,117,39,0,0,0,83,101,116,32,95,95,112,97, - 99,107,97,103,101,95,95,32,111,110,32,116,104,101,32,114, - 101,116,117,114,110,101,100,32,109,111,100,117,108,101,46,99, - 0,0,0,0,0,0,0,0,3,0,0,0,4,0,0,0, - 31,0,0,0,115,108,0,0,0,136,0,0,124,0,0,124, - 1,0,142,0,0,125,2,0,116,0,0,124,2,0,100,1, - 0,131,2,0,12,115,46,0,124,2,0,106,1,0,100,0, - 0,107,8,0,114,104,0,124,2,0,106,3,0,124,2,0, - 95,1,0,116,0,0,124,2,0,100,2,0,131,2,0,115, - 104,0,124,2,0,106,1,0,106,4,0,100,3,0,131,1, - 0,100,4,0,25,124,2,0,95,1,0,113,104,0,110,0, - 0,124,2,0,83,40,5,0,0,0,78,117,11,0,0,0, - 95,95,112,97,99,107,97,103,101,95,95,117,8,0,0,0, - 95,95,112,97,116,104,95,95,117,1,0,0,0,46,105,0, - 0,0,0,40,5,0,0,0,117,7,0,0,0,104,97,115, - 97,116,116,114,117,11,0,0,0,95,95,112,97,99,107,97, - 103,101,95,95,117,4,0,0,0,78,111,110,101,117,8,0, - 0,0,95,95,110,97,109,101,95,95,117,10,0,0,0,114, - 112,97,114,116,105,116,105,111,110,40,3,0,0,0,117,4, + 111,116,115,116,114,97,112,62,117,13,0,0,0,95,119,114, + 105,116,101,95,97,116,111,109,105,99,130,0,0,0,115,24, + 0,0,0,0,5,24,1,38,1,3,3,21,1,19,1,20, + 1,13,1,3,1,17,1,13,1,5,1,117,13,0,0,0, + 95,119,114,105,116,101,95,97,116,111,109,105,99,99,2,0, + 0,0,0,0,0,0,3,0,0,0,7,0,0,0,67,0, + 0,0,115,95,0,0,0,120,69,0,100,1,0,100,2,0, + 100,3,0,100,4,0,103,4,0,68,93,49,0,125,2,0, + 116,0,0,124,1,0,124,2,0,131,2,0,114,19,0,116, + 1,0,124,0,0,124,2,0,116,2,0,124,1,0,124,2, + 0,131,2,0,131,3,0,1,113,19,0,113,19,0,87,124, + 0,0,106,3,0,106,4,0,124,1,0,106,3,0,131,1, + 0,1,100,5,0,83,40,6,0,0,0,117,38,0,0,0, + 83,105,109,112,108,101,32,115,117,98,115,116,105,116,117,116, + 101,32,102,111,114,32,102,117,110,99,116,111,111,108,115,46, + 119,114,97,112,115,46,117,10,0,0,0,95,95,109,111,100, + 117,108,101,95,95,117,8,0,0,0,95,95,110,97,109,101, + 95,95,117,12,0,0,0,95,95,113,117,97,108,110,97,109, + 101,95,95,117,7,0,0,0,95,95,100,111,99,95,95,78, + 40,5,0,0,0,117,7,0,0,0,104,97,115,97,116,116, + 114,117,7,0,0,0,115,101,116,97,116,116,114,117,7,0, + 0,0,103,101,116,97,116,116,114,117,8,0,0,0,95,95, + 100,105,99,116,95,95,117,6,0,0,0,117,112,100,97,116, + 101,40,3,0,0,0,117,3,0,0,0,110,101,119,117,3, + 0,0,0,111,108,100,117,7,0,0,0,114,101,112,108,97, + 99,101,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,5, + 0,0,0,95,119,114,97,112,151,0,0,0,115,8,0,0, + 0,0,2,25,1,15,1,32,1,117,5,0,0,0,95,119, + 114,97,112,99,1,0,0,0,0,0,0,0,1,0,0,0, + 2,0,0,0,67,0,0,0,115,16,0,0,0,116,0,0, + 116,1,0,131,1,0,124,0,0,131,1,0,83,40,1,0, + 0,0,117,75,0,0,0,67,114,101,97,116,101,32,97,32, + 110,101,119,32,109,111,100,117,108,101,46,10,10,32,32,32, + 32,84,104,101,32,109,111,100,117,108,101,32,105,115,32,110, + 111,116,32,101,110,116,101,114,101,100,32,105,110,116,111,32, + 115,121,115,46,109,111,100,117,108,101,115,46,10,10,32,32, + 32,32,40,2,0,0,0,117,4,0,0,0,116,121,112,101, + 117,3,0,0,0,115,121,115,40,1,0,0,0,117,4,0, + 0,0,110,97,109,101,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,10,0,0,0,110,101,119,95,109,111,100,117,108, + 101,162,0,0,0,115,2,0,0,0,0,6,117,10,0,0, + 0,110,101,119,95,109,111,100,117,108,101,99,1,0,0,0, + 0,0,0,0,2,0,0,0,4,0,0,0,71,0,0,0, + 115,75,0,0,0,116,0,0,106,1,0,106,2,0,114,71, + 0,124,0,0,106,3,0,100,6,0,131,1,0,115,40,0, + 100,3,0,124,0,0,23,125,0,0,110,0,0,116,4,0, + 124,0,0,106,5,0,124,1,0,140,0,0,100,4,0,116, + 0,0,106,6,0,131,1,1,1,110,0,0,100,5,0,83, + 40,7,0,0,0,117,61,0,0,0,80,114,105,110,116,32, + 116,104,101,32,109,101,115,115,97,103,101,32,116,111,32,115, + 116,100,101,114,114,32,105,102,32,45,118,47,80,89,84,72, + 79,78,86,69,82,66,79,83,69,32,105,115,32,116,117,114, + 110,101,100,32,111,110,46,117,1,0,0,0,35,117,7,0, + 0,0,105,109,112,111,114,116,32,117,2,0,0,0,35,32, + 117,4,0,0,0,102,105,108,101,78,40,2,0,0,0,117, + 1,0,0,0,35,117,7,0,0,0,105,109,112,111,114,116, + 32,40,7,0,0,0,117,3,0,0,0,115,121,115,117,5, + 0,0,0,102,108,97,103,115,117,7,0,0,0,118,101,114, + 98,111,115,101,117,10,0,0,0,115,116,97,114,116,115,119, + 105,116,104,117,5,0,0,0,112,114,105,110,116,117,6,0, + 0,0,102,111,114,109,97,116,117,6,0,0,0,115,116,100, + 101,114,114,40,2,0,0,0,117,7,0,0,0,109,101,115, + 115,97,103,101,117,4,0,0,0,97,114,103,115,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,15,0,0,0,118,101, + 114,98,111,115,101,95,109,101,115,115,97,103,101,173,0,0, + 0,115,8,0,0,0,0,2,12,1,15,1,13,1,117,15, + 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, + 103,101,99,1,0,0,0,0,0,0,0,2,0,0,0,3, + 0,0,0,3,0,0,0,115,35,0,0,0,135,0,0,102, + 1,0,100,1,0,100,2,0,134,0,0,125,1,0,116,0, + 0,124,1,0,136,0,0,131,2,0,1,124,1,0,83,40, + 3,0,0,0,117,39,0,0,0,83,101,116,32,95,95,112, + 97,99,107,97,103,101,95,95,32,111,110,32,116,104,101,32, + 114,101,116,117,114,110,101,100,32,109,111,100,117,108,101,46, + 99,0,0,0,0,0,0,0,0,3,0,0,0,4,0,0, + 0,31,0,0,0,115,108,0,0,0,136,0,0,124,0,0, + 124,1,0,142,0,0,125,2,0,116,0,0,124,2,0,100, + 1,0,131,2,0,12,115,46,0,124,2,0,106,1,0,100, + 0,0,107,8,0,114,104,0,124,2,0,106,3,0,124,2, + 0,95,1,0,116,0,0,124,2,0,100,2,0,131,2,0, + 115,104,0,124,2,0,106,1,0,106,4,0,100,3,0,131, + 1,0,100,4,0,25,124,2,0,95,1,0,113,104,0,110, + 0,0,124,2,0,83,40,5,0,0,0,78,117,11,0,0, + 0,95,95,112,97,99,107,97,103,101,95,95,117,8,0,0, + 0,95,95,112,97,116,104,95,95,117,1,0,0,0,46,105, + 0,0,0,0,40,5,0,0,0,117,7,0,0,0,104,97, + 115,97,116,116,114,117,11,0,0,0,95,95,112,97,99,107, + 97,103,101,95,95,117,4,0,0,0,78,111,110,101,117,8, + 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, + 114,112,97,114,116,105,116,105,111,110,40,3,0,0,0,117, + 4,0,0,0,97,114,103,115,117,6,0,0,0,107,119,97, + 114,103,115,117,6,0,0,0,109,111,100,117,108,101,40,1, + 0,0,0,117,3,0,0,0,102,120,110,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,19,0,0,0,115,101,116,95,112,97,99,107,97, + 103,101,95,119,114,97,112,112,101,114,183,0,0,0,115,12, + 0,0,0,0,1,15,1,31,1,12,1,15,1,31,1,117, + 40,0,0,0,115,101,116,95,112,97,99,107,97,103,101,46, + 60,108,111,99,97,108,115,62,46,115,101,116,95,112,97,99, + 107,97,103,101,95,119,114,97,112,112,101,114,40,1,0,0, + 0,117,5,0,0,0,95,119,114,97,112,40,2,0,0,0, + 117,3,0,0,0,102,120,110,117,19,0,0,0,115,101,116, + 95,112,97,99,107,97,103,101,95,119,114,97,112,112,101,114, + 40,0,0,0,0,40,1,0,0,0,117,3,0,0,0,102, + 120,110,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,11,0,0,0,115,101,116,95,112,97,99, + 107,97,103,101,181,0,0,0,115,6,0,0,0,0,2,18, + 7,13,1,117,11,0,0,0,115,101,116,95,112,97,99,107, + 97,103,101,99,1,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,3,0,0,0,115,35,0,0,0,135,0,0, + 102,1,0,100,1,0,100,2,0,134,0,0,125,1,0,116, + 0,0,124,1,0,136,0,0,131,2,0,1,124,1,0,83, + 40,3,0,0,0,117,38,0,0,0,83,101,116,32,95,95, + 108,111,97,100,101,114,95,95,32,111,110,32,116,104,101,32, + 114,101,116,117,114,110,101,100,32,109,111,100,117,108,101,46, + 99,1,0,0,0,0,0,0,0,4,0,0,0,4,0,0, + 0,31,0,0,0,115,49,0,0,0,136,0,0,124,0,0, + 124,1,0,124,2,0,142,1,0,125,3,0,116,0,0,124, + 3,0,100,1,0,131,2,0,115,45,0,124,0,0,124,3, + 0,95,1,0,110,0,0,124,3,0,83,40,2,0,0,0, + 78,117,10,0,0,0,95,95,108,111,97,100,101,114,95,95, + 40,2,0,0,0,117,7,0,0,0,104,97,115,97,116,116, + 114,117,10,0,0,0,95,95,108,111,97,100,101,114,95,95, + 40,4,0,0,0,117,4,0,0,0,115,101,108,102,117,4, 0,0,0,97,114,103,115,117,6,0,0,0,107,119,97,114, 103,115,117,6,0,0,0,109,111,100,117,108,101,40,1,0, 0,0,117,3,0,0,0,102,120,110,40,0,0,0,0,117, 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,19,0,0,0,115,101,116,95,112,97,99,107,97,103, - 101,95,119,114,97,112,112,101,114,173,0,0,0,115,12,0, - 0,0,0,1,15,1,31,1,12,1,15,1,31,1,117,40, - 0,0,0,115,101,116,95,112,97,99,107,97,103,101,46,60, - 108,111,99,97,108,115,62,46,115,101,116,95,112,97,99,107, - 97,103,101,95,119,114,97,112,112,101,114,40,1,0,0,0, - 117,5,0,0,0,95,119,114,97,112,40,2,0,0,0,117, - 3,0,0,0,102,120,110,117,19,0,0,0,115,101,116,95, - 112,97,99,107,97,103,101,95,119,114,97,112,112,101,114,40, - 0,0,0,0,40,1,0,0,0,117,3,0,0,0,102,120, - 110,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,11,0,0,0,115,101,116,95,112,97,99,107, - 97,103,101,171,0,0,0,115,6,0,0,0,0,2,18,7, - 13,1,117,11,0,0,0,115,101,116,95,112,97,99,107,97, - 103,101,99,1,0,0,0,0,0,0,0,2,0,0,0,3, - 0,0,0,3,0,0,0,115,35,0,0,0,135,0,0,102, - 1,0,100,1,0,100,2,0,134,0,0,125,1,0,116,0, - 0,124,1,0,136,0,0,131,2,0,1,124,1,0,83,40, - 3,0,0,0,117,38,0,0,0,83,101,116,32,95,95,108, - 111,97,100,101,114,95,95,32,111,110,32,116,104,101,32,114, - 101,116,117,114,110,101,100,32,109,111,100,117,108,101,46,99, - 1,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, - 31,0,0,0,115,49,0,0,0,136,0,0,124,0,0,124, - 1,0,124,2,0,142,1,0,125,3,0,116,0,0,124,3, - 0,100,1,0,131,2,0,115,45,0,124,0,0,124,3,0, - 95,1,0,110,0,0,124,3,0,83,40,2,0,0,0,78, - 117,10,0,0,0,95,95,108,111,97,100,101,114,95,95,40, - 2,0,0,0,117,7,0,0,0,104,97,115,97,116,116,114, - 117,10,0,0,0,95,95,108,111,97,100,101,114,95,95,40, - 4,0,0,0,117,4,0,0,0,115,101,108,102,117,4,0, - 0,0,97,114,103,115,117,6,0,0,0,107,119,97,114,103, - 115,117,6,0,0,0,109,111,100,117,108,101,40,1,0,0, - 0,117,3,0,0,0,102,120,110,40,0,0,0,0,117,29, + 62,117,18,0,0,0,115,101,116,95,108,111,97,100,101,114, + 95,119,114,97,112,112,101,114,196,0,0,0,115,8,0,0, + 0,0,1,18,1,15,1,12,1,117,38,0,0,0,115,101, + 116,95,108,111,97,100,101,114,46,60,108,111,99,97,108,115, + 62,46,115,101,116,95,108,111,97,100,101,114,95,119,114,97, + 112,112,101,114,40,1,0,0,0,117,5,0,0,0,95,119, + 114,97,112,40,2,0,0,0,117,3,0,0,0,102,120,110, + 117,18,0,0,0,115,101,116,95,108,111,97,100,101,114,95, + 119,114,97,112,112,101,114,40,0,0,0,0,40,1,0,0, + 0,117,3,0,0,0,102,120,110,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,10,0,0,0, + 115,101,116,95,108,111,97,100,101,114,194,0,0,0,115,6, + 0,0,0,0,2,18,5,13,1,117,10,0,0,0,115,101, + 116,95,108,111,97,100,101,114,99,1,0,0,0,0,0,0, + 0,2,0,0,0,3,0,0,0,3,0,0,0,115,35,0, + 0,0,135,0,0,102,1,0,100,1,0,100,2,0,134,0, + 0,125,1,0,116,0,0,124,1,0,136,0,0,131,2,0, + 1,124,1,0,83,40,3,0,0,0,117,28,2,0,0,68, + 101,99,111,114,97,116,111,114,32,116,111,32,104,97,110,100, + 108,101,32,115,101,108,101,99,116,105,110,103,32,116,104,101, + 32,112,114,111,112,101,114,32,109,111,100,117,108,101,32,102, + 111,114,32,108,111,97,100,101,114,115,46,10,10,32,32,32, + 32,84,104,101,32,100,101,99,111,114,97,116,101,100,32,102, + 117,110,99,116,105,111,110,32,105,115,32,112,97,115,115,101, + 100,32,116,104,101,32,109,111,100,117,108,101,32,116,111,32, + 117,115,101,32,105,110,115,116,101,97,100,32,111,102,32,116, + 104,101,32,109,111,100,117,108,101,10,32,32,32,32,110,97, + 109,101,46,32,84,104,101,32,109,111,100,117,108,101,32,112, + 97,115,115,101,100,32,105,110,32,116,111,32,116,104,101,32, + 102,117,110,99,116,105,111,110,32,105,115,32,101,105,116,104, + 101,114,32,102,114,111,109,32,115,121,115,46,109,111,100,117, + 108,101,115,32,105,102,10,32,32,32,32,105,116,32,97,108, + 114,101,97,100,121,32,101,120,105,115,116,115,32,111,114,32, + 105,115,32,97,32,110,101,119,32,109,111,100,117,108,101,32, + 119,104,105,99,104,32,104,97,115,32,95,95,110,97,109,101, + 95,95,32,115,101,116,32,97,110,100,32,105,115,32,105,110, + 115,101,114,116,101,100,10,32,32,32,32,105,110,116,111,32, + 115,121,115,46,109,111,100,117,108,101,115,46,32,73,102,32, + 97,110,32,101,120,99,101,112,116,105,111,110,32,105,115,32, + 114,97,105,115,101,100,32,97,110,100,32,116,104,101,32,100, + 101,99,111,114,97,116,111,114,32,99,114,101,97,116,101,100, + 32,116,104,101,10,32,32,32,32,109,111,100,117,108,101,32, + 105,116,32,105,115,32,115,117,98,115,101,113,117,101,110,116, + 108,121,32,114,101,109,111,118,101,100,32,102,114,111,109,32, + 115,121,115,46,109,111,100,117,108,101,115,46,10,10,32,32, + 32,32,84,104,101,32,100,101,99,111,114,97,116,111,114,32, + 97,115,115,117,109,101,115,32,116,104,97,116,32,116,104,101, + 32,100,101,99,111,114,97,116,101,100,32,102,117,110,99,116, + 105,111,110,32,116,97,107,101,115,32,116,104,101,32,109,111, + 100,117,108,101,32,110,97,109,101,32,97,115,10,32,32,32, + 32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117, + 109,101,110,116,46,10,10,32,32,32,32,99,2,0,0,0, + 0,0,0,0,6,0,0,0,11,0,0,0,31,0,0,0, + 115,124,0,0,0,116,0,0,106,1,0,106,2,0,124,1, + 0,131,1,0,125,4,0,116,3,0,124,4,0,131,1,0, + 125,5,0,124,5,0,115,64,0,116,4,0,124,1,0,131, + 1,0,125,4,0,124,4,0,116,0,0,106,1,0,124,1, + 0,60,110,0,0,121,23,0,136,0,0,124,0,0,124,4, + 0,124,2,0,124,3,0,142,2,0,83,87,110,30,0,1, + 1,1,124,5,0,115,112,0,116,0,0,106,1,0,124,1, + 0,61,110,0,0,130,0,0,89,110,1,0,88,100,0,0, + 83,40,1,0,0,0,78,40,5,0,0,0,117,3,0,0, + 0,115,121,115,117,7,0,0,0,109,111,100,117,108,101,115, + 117,3,0,0,0,103,101,116,117,4,0,0,0,98,111,111, + 108,117,10,0,0,0,110,101,119,95,109,111,100,117,108,101, + 40,6,0,0,0,117,4,0,0,0,115,101,108,102,117,8, + 0,0,0,102,117,108,108,110,97,109,101,117,4,0,0,0, + 97,114,103,115,117,6,0,0,0,107,119,97,114,103,115,117, + 6,0,0,0,109,111,100,117,108,101,117,9,0,0,0,105, + 115,95,114,101,108,111,97,100,40,1,0,0,0,117,3,0, + 0,0,102,120,110,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,25,0,0, + 0,109,111,100,117,108,101,95,102,111,114,95,108,111,97,100, + 101,114,95,119,114,97,112,112,101,114,218,0,0,0,115,22, + 0,0,0,0,1,18,1,12,1,6,4,12,1,16,1,3, + 1,23,1,3,1,6,1,13,1,117,52,0,0,0,109,111, + 100,117,108,101,95,102,111,114,95,108,111,97,100,101,114,46, + 60,108,111,99,97,108,115,62,46,109,111,100,117,108,101,95, + 102,111,114,95,108,111,97,100,101,114,95,119,114,97,112,112, + 101,114,40,1,0,0,0,117,5,0,0,0,95,119,114,97, + 112,40,2,0,0,0,117,3,0,0,0,102,120,110,117,25, + 0,0,0,109,111,100,117,108,101,95,102,111,114,95,108,111, + 97,100,101,114,95,119,114,97,112,112,101,114,40,0,0,0, + 0,40,1,0,0,0,117,3,0,0,0,102,120,110,117,29, 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,18,0,0,0,115,101,116,95,108,111,97,100,101,114,95, - 119,114,97,112,112,101,114,186,0,0,0,115,8,0,0,0, - 0,1,18,1,15,1,12,1,117,38,0,0,0,115,101,116, - 95,108,111,97,100,101,114,46,60,108,111,99,97,108,115,62, - 46,115,101,116,95,108,111,97,100,101,114,95,119,114,97,112, + 117,17,0,0,0,109,111,100,117,108,101,95,102,111,114,95, + 108,111,97,100,101,114,205,0,0,0,115,6,0,0,0,0, + 13,18,15,13,1,117,17,0,0,0,109,111,100,117,108,101, + 95,102,111,114,95,108,111,97,100,101,114,99,1,0,0,0, + 0,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0, + 115,35,0,0,0,135,0,0,102,1,0,100,1,0,100,2, + 0,134,0,0,125,1,0,116,0,0,124,1,0,136,0,0, + 131,2,0,1,124,1,0,83,40,3,0,0,0,117,252,0, + 0,0,68,101,99,111,114,97,116,111,114,32,116,111,32,118, + 101,114,105,102,121,32,116,104,97,116,32,116,104,101,32,109, + 111,100,117,108,101,32,98,101,105,110,103,32,114,101,113,117, + 101,115,116,101,100,32,109,97,116,99,104,101,115,32,116,104, + 101,32,111,110,101,32,116,104,101,10,32,32,32,32,108,111, + 97,100,101,114,32,99,97,110,32,104,97,110,100,108,101,46, + 10,10,32,32,32,32,84,104,101,32,102,105,114,115,116,32, + 97,114,103,117,109,101,110,116,32,40,115,101,108,102,41,32, + 109,117,115,116,32,100,101,102,105,110,101,32,95,110,97,109, + 101,32,119,104,105,99,104,32,116,104,101,32,115,101,99,111, + 110,100,32,97,114,103,117,109,101,110,116,32,105,115,10,32, + 32,32,32,99,111,109,112,97,114,101,100,32,97,103,97,105, + 110,115,116,46,32,73,102,32,116,104,101,32,99,111,109,112, + 97,114,105,115,111,110,32,102,97,105,108,115,32,116,104,101, + 110,32,73,109,112,111,114,116,69,114,114,111,114,32,105,115, + 32,114,97,105,115,101,100,46,10,10,32,32,32,32,99,2, + 0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,31, + 0,0,0,115,59,0,0,0,124,0,0,106,0,0,124,1, + 0,107,3,0,114,40,0,116,1,0,100,1,0,124,1,0, + 22,100,2,0,124,1,0,131,1,1,130,1,0,110,0,0, + 136,0,0,124,0,0,124,1,0,124,2,0,124,3,0,142, + 2,0,83,40,3,0,0,0,78,117,23,0,0,0,108,111, + 97,100,101,114,32,99,97,110,110,111,116,32,104,97,110,100, + 108,101,32,37,115,117,4,0,0,0,110,97,109,101,40,2, + 0,0,0,117,5,0,0,0,95,110,97,109,101,117,11,0, + 0,0,73,109,112,111,114,116,69,114,114,111,114,40,4,0, + 0,0,117,4,0,0,0,115,101,108,102,117,4,0,0,0, + 110,97,109,101,117,4,0,0,0,97,114,103,115,117,6,0, + 0,0,107,119,97,114,103,115,40,1,0,0,0,117,6,0, + 0,0,109,101,116,104,111,100,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 19,0,0,0,95,99,104,101,99,107,95,110,97,109,101,95, + 119,114,97,112,112,101,114,245,0,0,0,115,6,0,0,0, + 0,1,15,1,25,1,117,40,0,0,0,95,99,104,101,99, + 107,95,110,97,109,101,46,60,108,111,99,97,108,115,62,46, + 95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112, 112,101,114,40,1,0,0,0,117,5,0,0,0,95,119,114, - 97,112,40,2,0,0,0,117,3,0,0,0,102,120,110,117, - 18,0,0,0,115,101,116,95,108,111,97,100,101,114,95,119, - 114,97,112,112,101,114,40,0,0,0,0,40,1,0,0,0, - 117,3,0,0,0,102,120,110,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,115, - 101,116,95,108,111,97,100,101,114,184,0,0,0,115,6,0, - 0,0,0,2,18,5,13,1,117,10,0,0,0,115,101,116, - 95,108,111,97,100,101,114,99,1,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,3,0,0,0,115,35,0,0, - 0,135,0,0,102,1,0,100,1,0,100,2,0,134,0,0, - 125,1,0,116,0,0,124,1,0,136,0,0,131,2,0,1, - 124,1,0,83,40,3,0,0,0,117,28,2,0,0,68,101, - 99,111,114,97,116,111,114,32,116,111,32,104,97,110,100,108, - 101,32,115,101,108,101,99,116,105,110,103,32,116,104,101,32, - 112,114,111,112,101,114,32,109,111,100,117,108,101,32,102,111, - 114,32,108,111,97,100,101,114,115,46,10,10,32,32,32,32, - 84,104,101,32,100,101,99,111,114,97,116,101,100,32,102,117, - 110,99,116,105,111,110,32,105,115,32,112,97,115,115,101,100, - 32,116,104,101,32,109,111,100,117,108,101,32,116,111,32,117, - 115,101,32,105,110,115,116,101,97,100,32,111,102,32,116,104, - 101,32,109,111,100,117,108,101,10,32,32,32,32,110,97,109, - 101,46,32,84,104,101,32,109,111,100,117,108,101,32,112,97, - 115,115,101,100,32,105,110,32,116,111,32,116,104,101,32,102, - 117,110,99,116,105,111,110,32,105,115,32,101,105,116,104,101, - 114,32,102,114,111,109,32,115,121,115,46,109,111,100,117,108, - 101,115,32,105,102,10,32,32,32,32,105,116,32,97,108,114, - 101,97,100,121,32,101,120,105,115,116,115,32,111,114,32,105, - 115,32,97,32,110,101,119,32,109,111,100,117,108,101,32,119, - 104,105,99,104,32,104,97,115,32,95,95,110,97,109,101,95, - 95,32,115,101,116,32,97,110,100,32,105,115,32,105,110,115, - 101,114,116,101,100,10,32,32,32,32,105,110,116,111,32,115, - 121,115,46,109,111,100,117,108,101,115,46,32,73,102,32,97, - 110,32,101,120,99,101,112,116,105,111,110,32,105,115,32,114, - 97,105,115,101,100,32,97,110,100,32,116,104,101,32,100,101, - 99,111,114,97,116,111,114,32,99,114,101,97,116,101,100,32, - 116,104,101,10,32,32,32,32,109,111,100,117,108,101,32,105, - 116,32,105,115,32,115,117,98,115,101,113,117,101,110,116,108, - 121,32,114,101,109,111,118,101,100,32,102,114,111,109,32,115, - 121,115,46,109,111,100,117,108,101,115,46,10,10,32,32,32, - 32,84,104,101,32,100,101,99,111,114,97,116,111,114,32,97, - 115,115,117,109,101,115,32,116,104,97,116,32,116,104,101,32, - 100,101,99,111,114,97,116,101,100,32,102,117,110,99,116,105, - 111,110,32,116,97,107,101,115,32,116,104,101,32,109,111,100, - 117,108,101,32,110,97,109,101,32,97,115,10,32,32,32,32, - 116,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109, - 101,110,116,46,10,10,32,32,32,32,99,2,0,0,0,0, - 0,0,0,6,0,0,0,11,0,0,0,31,0,0,0,115, - 127,0,0,0,116,0,0,106,1,0,106,2,0,124,1,0, - 131,1,0,125,4,0,116,3,0,124,4,0,131,1,0,125, - 5,0,124,5,0,115,67,0,116,4,0,106,5,0,124,1, - 0,131,1,0,125,4,0,124,4,0,116,0,0,106,1,0, - 124,1,0,60,110,0,0,121,23,0,136,0,0,124,0,0, - 124,4,0,124,2,0,124,3,0,142,2,0,83,87,110,30, - 0,1,1,1,124,5,0,115,115,0,116,0,0,106,1,0, - 124,1,0,61,110,0,0,130,0,0,89,110,1,0,88,100, - 0,0,83,40,1,0,0,0,78,40,6,0,0,0,117,3, - 0,0,0,115,121,115,117,7,0,0,0,109,111,100,117,108, - 101,115,117,3,0,0,0,103,101,116,117,4,0,0,0,98, - 111,111,108,117,3,0,0,0,105,109,112,117,10,0,0,0, - 110,101,119,95,109,111,100,117,108,101,40,6,0,0,0,117, - 4,0,0,0,115,101,108,102,117,8,0,0,0,102,117,108, - 108,110,97,109,101,117,4,0,0,0,97,114,103,115,117,6, - 0,0,0,107,119,97,114,103,115,117,6,0,0,0,109,111, - 100,117,108,101,117,9,0,0,0,105,115,95,114,101,108,111, - 97,100,40,1,0,0,0,117,3,0,0,0,102,120,110,40, + 97,112,40,2,0,0,0,117,6,0,0,0,109,101,116,104, + 111,100,117,19,0,0,0,95,99,104,101,99,107,95,110,97, + 109,101,95,119,114,97,112,112,101,114,40,0,0,0,0,40, + 1,0,0,0,117,6,0,0,0,109,101,116,104,111,100,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,11,0,0,0,95,99,104,101,99,107,95,110,97,109, + 101,237,0,0,0,115,6,0,0,0,0,8,18,4,13,1, + 117,11,0,0,0,95,99,104,101,99,107,95,110,97,109,101, + 99,1,0,0,0,0,0,0,0,2,0,0,0,3,0,0, + 0,3,0,0,0,115,35,0,0,0,135,0,0,102,1,0, + 100,1,0,100,2,0,134,0,0,125,1,0,116,0,0,124, + 1,0,136,0,0,131,2,0,1,124,1,0,83,40,3,0, + 0,0,117,49,0,0,0,68,101,99,111,114,97,116,111,114, + 32,116,111,32,118,101,114,105,102,121,32,116,104,101,32,110, + 97,109,101,100,32,109,111,100,117,108,101,32,105,115,32,98, + 117,105,108,116,45,105,110,46,99,2,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,19,0,0,0,115,58,0, + 0,0,124,1,0,116,0,0,106,1,0,107,7,0,114,45, + 0,116,2,0,100,1,0,106,3,0,124,1,0,131,1,0, + 100,2,0,124,1,0,131,1,1,130,1,0,110,0,0,136, + 0,0,124,0,0,124,1,0,131,2,0,83,40,3,0,0, + 0,78,117,28,0,0,0,123,48,125,32,105,115,32,110,111, + 116,32,97,32,98,117,105,108,116,45,105,110,32,109,111,100, + 117,108,101,117,4,0,0,0,110,97,109,101,40,4,0,0, + 0,117,3,0,0,0,115,121,115,117,20,0,0,0,98,117, + 105,108,116,105,110,95,109,111,100,117,108,101,95,110,97,109, + 101,115,117,11,0,0,0,73,109,112,111,114,116,69,114,114, + 111,114,117,6,0,0,0,102,111,114,109,97,116,40,2,0, + 0,0,117,4,0,0,0,115,101,108,102,117,8,0,0,0, + 102,117,108,108,110,97,109,101,40,1,0,0,0,117,3,0, + 0,0,102,120,110,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,25,0,0, + 0,95,114,101,113,117,105,114,101,115,95,98,117,105,108,116, + 105,110,95,119,114,97,112,112,101,114,255,0,0,0,115,8, + 0,0,0,0,1,15,1,18,1,12,1,117,52,0,0,0, + 95,114,101,113,117,105,114,101,115,95,98,117,105,108,116,105, + 110,46,60,108,111,99,97,108,115,62,46,95,114,101,113,117, + 105,114,101,115,95,98,117,105,108,116,105,110,95,119,114,97, + 112,112,101,114,40,1,0,0,0,117,5,0,0,0,95,119, + 114,97,112,40,2,0,0,0,117,3,0,0,0,102,120,110, + 117,25,0,0,0,95,114,101,113,117,105,114,101,115,95,98, + 117,105,108,116,105,110,95,119,114,97,112,112,101,114,40,0, + 0,0,0,40,1,0,0,0,117,3,0,0,0,102,120,110, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,17,0,0,0,95,114,101,113,117,105,114,101,115, + 95,98,117,105,108,116,105,110,253,0,0,0,115,6,0,0, + 0,0,2,18,5,13,1,117,17,0,0,0,95,114,101,113, + 117,105,114,101,115,95,98,117,105,108,116,105,110,99,1,0, + 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, + 0,0,115,35,0,0,0,135,0,0,102,1,0,100,1,0, + 100,2,0,134,0,0,125,1,0,116,0,0,124,1,0,136, + 0,0,131,2,0,1,124,1,0,83,40,3,0,0,0,117, + 47,0,0,0,68,101,99,111,114,97,116,111,114,32,116,111, + 32,118,101,114,105,102,121,32,116,104,101,32,110,97,109,101, + 100,32,109,111,100,117,108,101,32,105,115,32,102,114,111,122, + 101,110,46,99,2,0,0,0,0,0,0,0,2,0,0,0, + 4,0,0,0,19,0,0,0,115,58,0,0,0,116,0,0, + 106,1,0,124,1,0,131,1,0,115,45,0,116,2,0,100, + 1,0,106,3,0,124,1,0,131,1,0,100,2,0,124,1, + 0,131,1,1,130,1,0,110,0,0,136,0,0,124,0,0, + 124,1,0,131,2,0,83,40,3,0,0,0,78,117,26,0, + 0,0,123,48,125,32,105,115,32,110,111,116,32,97,32,102, + 114,111,122,101,110,32,109,111,100,117,108,101,117,4,0,0, + 0,110,97,109,101,40,4,0,0,0,117,4,0,0,0,95, + 105,109,112,117,9,0,0,0,105,115,95,102,114,111,122,101, + 110,117,11,0,0,0,73,109,112,111,114,116,69,114,114,111, + 114,117,6,0,0,0,102,111,114,109,97,116,40,2,0,0, + 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,102, + 117,108,108,110,97,109,101,40,1,0,0,0,117,3,0,0, + 0,102,120,110,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,24,0,0,0, + 95,114,101,113,117,105,114,101,115,95,102,114,111,122,101,110, + 95,119,114,97,112,112,101,114,10,1,0,0,115,8,0,0, + 0,0,1,15,1,18,1,12,1,117,50,0,0,0,95,114, + 101,113,117,105,114,101,115,95,102,114,111,122,101,110,46,60, + 108,111,99,97,108,115,62,46,95,114,101,113,117,105,114,101, + 115,95,102,114,111,122,101,110,95,119,114,97,112,112,101,114, + 40,1,0,0,0,117,5,0,0,0,95,119,114,97,112,40, + 2,0,0,0,117,3,0,0,0,102,120,110,117,24,0,0, + 0,95,114,101,113,117,105,114,101,115,95,102,114,111,122,101, + 110,95,119,114,97,112,112,101,114,40,0,0,0,0,40,1, + 0,0,0,117,3,0,0,0,102,120,110,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,16,0, + 0,0,95,114,101,113,117,105,114,101,115,95,102,114,111,122, + 101,110,8,1,0,0,115,6,0,0,0,0,2,18,5,13, + 1,117,16,0,0,0,95,114,101,113,117,105,114,101,115,95, + 102,114,111,122,101,110,99,1,0,0,0,0,0,0,0,1, + 0,0,0,3,0,0,0,3,0,0,0,115,29,0,0,0, + 135,0,0,102,1,0,100,1,0,100,2,0,134,0,0,116, + 0,0,106,1,0,131,0,0,68,131,1,0,83,40,3,0, + 0,0,117,58,0,0,0,82,101,116,117,114,110,32,97,32, + 108,105,115,116,32,111,102,32,102,105,108,101,32,115,117,102, + 102,105,120,101,115,32,98,97,115,101,100,32,111,110,32,116, + 104,101,32,105,109,112,32,102,105,108,101,32,116,121,112,101, + 46,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, + 0,0,19,0,0,0,115,42,0,0,0,103,0,0,124,0, + 0,93,32,0,125,1,0,124,1,0,100,0,0,25,136,0, + 0,107,2,0,114,6,0,124,1,0,100,1,0,25,145,2, + 0,113,6,0,83,40,2,0,0,0,105,2,0,0,0,105, + 0,0,0,0,40,0,0,0,0,40,2,0,0,0,117,2, + 0,0,0,46,48,117,6,0,0,0,115,117,102,102,105,120, + 40,1,0,0,0,117,11,0,0,0,115,117,102,102,105,120, + 95,116,121,112,101,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, + 0,60,108,105,115,116,99,111,109,112,62,21,1,0,0,115, + 4,0,0,0,9,0,3,1,117,32,0,0,0,95,115,117, + 102,102,105,120,95,108,105,115,116,46,60,108,111,99,97,108, + 115,62,46,60,108,105,115,116,99,111,109,112,62,40,2,0, + 0,0,117,4,0,0,0,95,105,109,112,117,12,0,0,0, + 103,101,116,95,115,117,102,102,105,120,101,115,40,1,0,0, + 0,117,11,0,0,0,115,117,102,102,105,120,95,116,121,112, + 101,40,0,0,0,0,40,1,0,0,0,117,11,0,0,0, + 115,117,102,102,105,120,95,116,121,112,101,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,12,0, + 0,0,95,115,117,102,102,105,120,95,108,105,115,116,19,1, + 0,0,115,2,0,0,0,0,2,117,12,0,0,0,95,115, + 117,102,102,105,120,95,108,105,115,116,99,1,0,0,0,0, + 0,0,0,1,0,0,0,6,0,0,0,66,0,0,0,115, + 155,0,0,0,124,0,0,69,101,0,0,90,1,0,100,0, + 0,90,2,0,100,1,0,90,3,0,101,4,0,100,12,0, + 100,2,0,100,3,0,132,1,0,131,1,0,90,6,0,101, + 4,0,101,7,0,101,8,0,101,9,0,100,4,0,100,5, + 0,132,0,0,131,1,0,131,1,0,131,1,0,131,1,0, + 90,10,0,101,4,0,101,9,0,100,6,0,100,7,0,132, + 0,0,131,1,0,131,1,0,90,11,0,101,4,0,101,9, + 0,100,8,0,100,9,0,132,0,0,131,1,0,131,1,0, + 90,12,0,101,4,0,101,9,0,100,10,0,100,11,0,132, + 0,0,131,1,0,131,1,0,90,13,0,100,12,0,83,40, + 13,0,0,0,117,15,0,0,0,66,117,105,108,116,105,110, + 73,109,112,111,114,116,101,114,117,144,0,0,0,77,101,116, + 97,32,112,97,116,104,32,105,109,112,111,114,116,32,102,111, + 114,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, + 101,115,46,10,10,32,32,32,32,65,108,108,32,109,101,116, + 104,111,100,115,32,97,114,101,32,101,105,116,104,101,114,32, + 99,108,97,115,115,32,111,114,32,115,116,97,116,105,99,32, + 109,101,116,104,111,100,115,32,116,111,32,97,118,111,105,100, + 32,116,104,101,32,110,101,101,100,32,116,111,10,32,32,32, + 32,105,110,115,116,97,110,116,105,97,116,101,32,116,104,101, + 32,99,108,97,115,115,46,10,10,32,32,32,32,99,3,0, + 0,0,0,0,0,0,3,0,0,0,2,0,0,0,67,0, + 0,0,115,39,0,0,0,124,2,0,100,1,0,107,9,0, + 114,16,0,100,1,0,83,116,1,0,106,2,0,124,1,0, + 131,1,0,114,35,0,124,0,0,83,100,1,0,83,40,2, + 0,0,0,117,113,0,0,0,70,105,110,100,32,116,104,101, + 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, + 46,10,10,32,32,32,32,32,32,32,32,73,102,32,39,112, + 97,116,104,39,32,105,115,32,101,118,101,114,32,115,112,101, + 99,105,102,105,101,100,32,116,104,101,110,32,116,104,101,32, + 115,101,97,114,99,104,32,105,115,32,99,111,110,115,105,100, + 101,114,101,100,32,97,32,102,97,105,108,117,114,101,46,10, + 10,32,32,32,32,32,32,32,32,78,40,3,0,0,0,117, + 4,0,0,0,78,111,110,101,117,4,0,0,0,95,105,109, + 112,117,10,0,0,0,105,115,95,98,117,105,108,116,105,110, + 40,3,0,0,0,117,3,0,0,0,99,108,115,117,8,0, + 0,0,102,117,108,108,110,97,109,101,117,4,0,0,0,112, + 97,116,104,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 11,0,0,0,102,105,110,100,95,109,111,100,117,108,101,36, + 1,0,0,115,6,0,0,0,0,7,12,1,4,1,117,27, + 0,0,0,66,117,105,108,116,105,110,73,109,112,111,114,116, + 101,114,46,102,105,110,100,95,109,111,100,117,108,101,99,2, + 0,0,0,0,0,0,0,3,0,0,0,9,0,0,0,67, + 0,0,0,115,85,0,0,0,124,1,0,116,0,0,106,1, + 0,107,6,0,125,2,0,121,17,0,116,2,0,106,3,0, + 124,1,0,131,1,0,83,87,110,46,0,1,1,1,124,2, + 0,12,114,73,0,124,1,0,116,0,0,106,1,0,107,6, + 0,114,73,0,116,0,0,106,1,0,124,1,0,61,110,0, + 0,130,0,0,89,110,1,0,88,100,1,0,83,40,2,0, + 0,0,117,23,0,0,0,76,111,97,100,32,97,32,98,117, + 105,108,116,45,105,110,32,109,111,100,117,108,101,46,78,40, + 4,0,0,0,117,3,0,0,0,115,121,115,117,7,0,0, + 0,109,111,100,117,108,101,115,117,4,0,0,0,95,105,109, + 112,117,12,0,0,0,105,110,105,116,95,98,117,105,108,116, + 105,110,40,3,0,0,0,117,3,0,0,0,99,108,115,117, + 8,0,0,0,102,117,108,108,110,97,109,101,117,9,0,0, + 0,105,115,95,114,101,108,111,97,100,40,0,0,0,0,40, 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,25,0,0,0,109,111,100,117,108, - 101,95,102,111,114,95,108,111,97,100,101,114,95,119,114,97, - 112,112,101,114,208,0,0,0,115,22,0,0,0,0,1,18, - 1,12,1,6,4,15,1,16,1,3,1,23,1,3,1,6, - 1,13,1,117,52,0,0,0,109,111,100,117,108,101,95,102, - 111,114,95,108,111,97,100,101,114,46,60,108,111,99,97,108, - 115,62,46,109,111,100,117,108,101,95,102,111,114,95,108,111, - 97,100,101,114,95,119,114,97,112,112,101,114,40,1,0,0, - 0,117,5,0,0,0,95,119,114,97,112,40,2,0,0,0, - 117,3,0,0,0,102,120,110,117,25,0,0,0,109,111,100, - 117,108,101,95,102,111,114,95,108,111,97,100,101,114,95,119, - 114,97,112,112,101,114,40,0,0,0,0,40,1,0,0,0, - 117,3,0,0,0,102,120,110,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,17,0,0,0,109, - 111,100,117,108,101,95,102,111,114,95,108,111,97,100,101,114, - 195,0,0,0,115,6,0,0,0,0,13,18,15,13,1,117, - 17,0,0,0,109,111,100,117,108,101,95,102,111,114,95,108, - 111,97,100,101,114,99,1,0,0,0,0,0,0,0,2,0, - 0,0,3,0,0,0,3,0,0,0,115,35,0,0,0,135, - 0,0,102,1,0,100,1,0,100,2,0,134,0,0,125,1, - 0,116,0,0,124,1,0,136,0,0,131,2,0,1,124,1, - 0,83,40,3,0,0,0,117,252,0,0,0,68,101,99,111, - 114,97,116,111,114,32,116,111,32,118,101,114,105,102,121,32, - 116,104,97,116,32,116,104,101,32,109,111,100,117,108,101,32, - 98,101,105,110,103,32,114,101,113,117,101,115,116,101,100,32, - 109,97,116,99,104,101,115,32,116,104,101,32,111,110,101,32, - 116,104,101,10,32,32,32,32,108,111,97,100,101,114,32,99, - 97,110,32,104,97,110,100,108,101,46,10,10,32,32,32,32, - 84,104,101,32,102,105,114,115,116,32,97,114,103,117,109,101, - 110,116,32,40,115,101,108,102,41,32,109,117,115,116,32,100, - 101,102,105,110,101,32,95,110,97,109,101,32,119,104,105,99, - 104,32,116,104,101,32,115,101,99,111,110,100,32,97,114,103, - 117,109,101,110,116,32,105,115,10,32,32,32,32,99,111,109, - 112,97,114,101,100,32,97,103,97,105,110,115,116,46,32,73, - 102,32,116,104,101,32,99,111,109,112,97,114,105,115,111,110, - 32,102,97,105,108,115,32,116,104,101,110,32,73,109,112,111, - 114,116,69,114,114,111,114,32,105,115,32,114,97,105,115,101, - 100,46,10,10,32,32,32,32,99,2,0,0,0,0,0,0, - 0,4,0,0,0,5,0,0,0,31,0,0,0,115,59,0, - 0,0,124,0,0,106,0,0,124,1,0,107,3,0,114,40, - 0,116,1,0,100,1,0,124,1,0,22,100,2,0,124,1, - 0,131,1,1,130,1,0,110,0,0,136,0,0,124,0,0, - 124,1,0,124,2,0,124,3,0,142,2,0,83,40,3,0, - 0,0,78,117,23,0,0,0,108,111,97,100,101,114,32,99, - 97,110,110,111,116,32,104,97,110,100,108,101,32,37,115,117, - 4,0,0,0,110,97,109,101,40,2,0,0,0,117,5,0, - 0,0,95,110,97,109,101,117,11,0,0,0,73,109,112,111, - 114,116,69,114,114,111,114,40,4,0,0,0,117,4,0,0, - 0,115,101,108,102,117,4,0,0,0,110,97,109,101,117,4, - 0,0,0,97,114,103,115,117,6,0,0,0,107,119,97,114, - 103,115,40,1,0,0,0,117,6,0,0,0,109,101,116,104, - 111,100,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,19,0,0,0,95,99, - 104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,101, - 114,235,0,0,0,115,6,0,0,0,0,1,15,1,25,1, - 117,40,0,0,0,95,99,104,101,99,107,95,110,97,109,101, - 46,60,108,111,99,97,108,115,62,46,95,99,104,101,99,107, - 95,110,97,109,101,95,119,114,97,112,112,101,114,40,1,0, - 0,0,117,5,0,0,0,95,119,114,97,112,40,2,0,0, - 0,117,6,0,0,0,109,101,116,104,111,100,117,19,0,0, - 0,95,99,104,101,99,107,95,110,97,109,101,95,119,114,97, - 112,112,101,114,40,0,0,0,0,40,1,0,0,0,117,6, - 0,0,0,109,101,116,104,111,100,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, - 95,99,104,101,99,107,95,110,97,109,101,227,0,0,0,115, - 6,0,0,0,0,8,18,4,13,1,117,11,0,0,0,95, - 99,104,101,99,107,95,110,97,109,101,99,1,0,0,0,0, - 0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,115, - 35,0,0,0,135,0,0,102,1,0,100,1,0,100,2,0, - 134,0,0,125,1,0,116,0,0,124,1,0,136,0,0,131, - 2,0,1,124,1,0,83,40,3,0,0,0,117,49,0,0, - 0,68,101,99,111,114,97,116,111,114,32,116,111,32,118,101, - 114,105,102,121,32,116,104,101,32,110,97,109,101,100,32,109, - 111,100,117,108,101,32,105,115,32,98,117,105,108,116,45,105, - 110,46,99,2,0,0,0,0,0,0,0,2,0,0,0,4, - 0,0,0,19,0,0,0,115,58,0,0,0,124,1,0,116, - 0,0,106,1,0,107,7,0,114,45,0,116,2,0,100,1, - 0,106,3,0,124,1,0,131,1,0,100,2,0,124,1,0, - 131,1,1,130,1,0,110,0,0,136,0,0,124,0,0,124, - 1,0,131,2,0,83,40,3,0,0,0,78,117,28,0,0, - 0,123,48,125,32,105,115,32,110,111,116,32,97,32,98,117, - 105,108,116,45,105,110,32,109,111,100,117,108,101,117,4,0, - 0,0,110,97,109,101,40,4,0,0,0,117,3,0,0,0, - 115,121,115,117,20,0,0,0,98,117,105,108,116,105,110,95, - 109,111,100,117,108,101,95,110,97,109,101,115,117,11,0,0, - 0,73,109,112,111,114,116,69,114,114,111,114,117,6,0,0, - 0,102,111,114,109,97,116,40,2,0,0,0,117,4,0,0, - 0,115,101,108,102,117,8,0,0,0,102,117,108,108,110,97, - 109,101,40,1,0,0,0,117,3,0,0,0,102,120,110,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,25,0,0,0,95,114,101,113,117, - 105,114,101,115,95,98,117,105,108,116,105,110,95,119,114,97, - 112,112,101,114,245,0,0,0,115,8,0,0,0,0,1,15, - 1,18,1,12,1,117,52,0,0,0,95,114,101,113,117,105, - 114,101,115,95,98,117,105,108,116,105,110,46,60,108,111,99, - 97,108,115,62,46,95,114,101,113,117,105,114,101,115,95,98, - 117,105,108,116,105,110,95,119,114,97,112,112,101,114,40,1, - 0,0,0,117,5,0,0,0,95,119,114,97,112,40,2,0, - 0,0,117,3,0,0,0,102,120,110,117,25,0,0,0,95, - 114,101,113,117,105,114,101,115,95,98,117,105,108,116,105,110, - 95,119,114,97,112,112,101,114,40,0,0,0,0,40,1,0, - 0,0,117,3,0,0,0,102,120,110,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,17,0,0, - 0,95,114,101,113,117,105,114,101,115,95,98,117,105,108,116, - 105,110,243,0,0,0,115,6,0,0,0,0,2,18,5,13, - 1,117,17,0,0,0,95,114,101,113,117,105,114,101,115,95, - 98,117,105,108,116,105,110,99,1,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,3,0,0,0,115,35,0,0, - 0,135,0,0,102,1,0,100,1,0,100,2,0,134,0,0, - 125,1,0,116,0,0,124,1,0,136,0,0,131,2,0,1, - 124,1,0,83,40,3,0,0,0,117,47,0,0,0,68,101, - 99,111,114,97,116,111,114,32,116,111,32,118,101,114,105,102, - 121,32,116,104,101,32,110,97,109,101,100,32,109,111,100,117, - 108,101,32,105,115,32,102,114,111,122,101,110,46,99,2,0, - 0,0,0,0,0,0,2,0,0,0,4,0,0,0,19,0, - 0,0,115,58,0,0,0,116,0,0,106,1,0,124,1,0, - 131,1,0,115,45,0,116,2,0,100,1,0,106,3,0,124, - 1,0,131,1,0,100,2,0,124,1,0,131,1,1,130,1, - 0,110,0,0,136,0,0,124,0,0,124,1,0,131,2,0, - 83,40,3,0,0,0,78,117,26,0,0,0,123,48,125,32, - 105,115,32,110,111,116,32,97,32,102,114,111,122,101,110,32, - 109,111,100,117,108,101,117,4,0,0,0,110,97,109,101,40, - 4,0,0,0,117,3,0,0,0,105,109,112,117,9,0,0, - 0,105,115,95,102,114,111,122,101,110,117,11,0,0,0,73, - 109,112,111,114,116,69,114,114,111,114,117,6,0,0,0,102, - 111,114,109,97,116,40,2,0,0,0,117,4,0,0,0,115, - 101,108,102,117,8,0,0,0,102,117,108,108,110,97,109,101, - 40,1,0,0,0,117,3,0,0,0,102,120,110,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,24,0,0,0,95,114,101,113,117,105,114, - 101,115,95,102,114,111,122,101,110,95,119,114,97,112,112,101, - 114,0,1,0,0,115,8,0,0,0,0,1,15,1,18,1, - 12,1,117,50,0,0,0,95,114,101,113,117,105,114,101,115, - 95,102,114,111,122,101,110,46,60,108,111,99,97,108,115,62, - 46,95,114,101,113,117,105,114,101,115,95,102,114,111,122,101, - 110,95,119,114,97,112,112,101,114,40,1,0,0,0,117,5, - 0,0,0,95,119,114,97,112,40,2,0,0,0,117,3,0, - 0,0,102,120,110,117,24,0,0,0,95,114,101,113,117,105, - 114,101,115,95,102,114,111,122,101,110,95,119,114,97,112,112, - 101,114,40,0,0,0,0,40,1,0,0,0,117,3,0,0, - 0,102,120,110,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,16,0,0,0,95,114,101,113,117, - 105,114,101,115,95,102,114,111,122,101,110,254,0,0,0,115, - 6,0,0,0,0,2,18,5,13,1,117,16,0,0,0,95, - 114,101,113,117,105,114,101,115,95,102,114,111,122,101,110,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 3,0,0,0,115,29,0,0,0,135,0,0,102,1,0,100, - 1,0,100,2,0,134,0,0,116,0,0,106,1,0,131,0, - 0,68,131,1,0,83,40,3,0,0,0,117,58,0,0,0, - 82,101,116,117,114,110,32,97,32,108,105,115,116,32,111,102, - 32,102,105,108,101,32,115,117,102,102,105,120,101,115,32,98, - 97,115,101,100,32,111,110,32,116,104,101,32,105,109,112,32, - 102,105,108,101,32,116,121,112,101,46,99,1,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,19,0,0,0,115, - 42,0,0,0,103,0,0,124,0,0,93,32,0,125,1,0, - 124,1,0,100,0,0,25,136,0,0,107,2,0,114,6,0, - 124,1,0,100,1,0,25,145,2,0,113,6,0,83,40,2, - 0,0,0,105,2,0,0,0,105,0,0,0,0,40,0,0, - 0,0,40,2,0,0,0,117,2,0,0,0,46,48,117,6, - 0,0,0,115,117,102,102,105,120,40,1,0,0,0,117,11, - 0,0,0,115,117,102,102,105,120,95,116,121,112,101,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,10,0,0,0,60,108,105,115,116,99, - 111,109,112,62,11,1,0,0,115,4,0,0,0,9,0,3, - 1,117,32,0,0,0,95,115,117,102,102,105,120,95,108,105, - 115,116,46,60,108,111,99,97,108,115,62,46,60,108,105,115, - 116,99,111,109,112,62,40,2,0,0,0,117,3,0,0,0, - 105,109,112,117,12,0,0,0,103,101,116,95,115,117,102,102, - 105,120,101,115,40,1,0,0,0,117,11,0,0,0,115,117, - 102,102,105,120,95,116,121,112,101,40,0,0,0,0,40,1, - 0,0,0,117,11,0,0,0,115,117,102,102,105,120,95,116, - 121,112,101,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,12,0,0,0,95,115,117,102,102,105, - 120,95,108,105,115,116,9,1,0,0,115,2,0,0,0,0, - 2,117,12,0,0,0,95,115,117,102,102,105,120,95,108,105, - 115,116,99,1,0,0,0,0,0,0,0,1,0,0,0,6, - 0,0,0,66,0,0,0,115,155,0,0,0,124,0,0,69, - 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, - 3,0,101,4,0,100,12,0,100,2,0,100,3,0,132,1, - 0,131,1,0,90,6,0,101,4,0,101,7,0,101,8,0, - 101,9,0,100,4,0,100,5,0,132,0,0,131,1,0,131, - 1,0,131,1,0,131,1,0,90,10,0,101,4,0,101,9, - 0,100,6,0,100,7,0,132,0,0,131,1,0,131,1,0, - 90,11,0,101,4,0,101,9,0,100,8,0,100,9,0,132, - 0,0,131,1,0,131,1,0,90,12,0,101,4,0,101,9, - 0,100,10,0,100,11,0,132,0,0,131,1,0,131,1,0, - 90,13,0,100,12,0,83,40,13,0,0,0,117,15,0,0, - 0,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, - 117,144,0,0,0,77,101,116,97,32,112,97,116,104,32,105, - 109,112,111,114,116,32,102,111,114,32,98,117,105,108,116,45, - 105,110,32,109,111,100,117,108,101,115,46,10,10,32,32,32, - 32,65,108,108,32,109,101,116,104,111,100,115,32,97,114,101, - 32,101,105,116,104,101,114,32,99,108,97,115,115,32,111,114, - 32,115,116,97,116,105,99,32,109,101,116,104,111,100,115,32, - 116,111,32,97,118,111,105,100,32,116,104,101,32,110,101,101, - 100,32,116,111,10,32,32,32,32,105,110,115,116,97,110,116, - 105,97,116,101,32,116,104,101,32,99,108,97,115,115,46,10, - 10,32,32,32,32,99,3,0,0,0,0,0,0,0,3,0, - 0,0,2,0,0,0,67,0,0,0,115,39,0,0,0,124, - 2,0,100,1,0,107,9,0,114,16,0,100,1,0,83,116, - 1,0,106,2,0,124,1,0,131,1,0,114,35,0,124,0, - 0,83,100,1,0,83,40,2,0,0,0,117,113,0,0,0, - 70,105,110,100,32,116,104,101,32,98,117,105,108,116,45,105, - 110,32,109,111,100,117,108,101,46,10,10,32,32,32,32,32, - 32,32,32,73,102,32,39,112,97,116,104,39,32,105,115,32, - 101,118,101,114,32,115,112,101,99,105,102,105,101,100,32,116, - 104,101,110,32,116,104,101,32,115,101,97,114,99,104,32,105, - 115,32,99,111,110,115,105,100,101,114,101,100,32,97,32,102, - 97,105,108,117,114,101,46,10,10,32,32,32,32,32,32,32, - 32,78,40,3,0,0,0,117,4,0,0,0,78,111,110,101, - 117,3,0,0,0,105,109,112,117,10,0,0,0,105,115,95, - 98,117,105,108,116,105,110,40,3,0,0,0,117,3,0,0, - 0,99,108,115,117,8,0,0,0,102,117,108,108,110,97,109, - 101,117,4,0,0,0,112,97,116,104,40,0,0,0,0,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,11,0,0,0,102,105,110,100,95, - 109,111,100,117,108,101,26,1,0,0,115,6,0,0,0,0, - 7,12,1,4,1,117,27,0,0,0,66,117,105,108,116,105, - 110,73,109,112,111,114,116,101,114,46,102,105,110,100,95,109, - 111,100,117,108,101,99,2,0,0,0,0,0,0,0,3,0, - 0,0,9,0,0,0,67,0,0,0,115,85,0,0,0,124, - 1,0,116,0,0,106,1,0,107,6,0,125,2,0,121,17, - 0,116,2,0,106,3,0,124,1,0,131,1,0,83,87,110, - 46,0,1,1,1,124,2,0,12,114,73,0,124,1,0,116, - 0,0,106,1,0,107,6,0,114,73,0,116,0,0,106,1, - 0,124,1,0,61,110,0,0,130,0,0,89,110,1,0,88, - 100,1,0,83,40,2,0,0,0,117,23,0,0,0,76,111, - 97,100,32,97,32,98,117,105,108,116,45,105,110,32,109,111, - 100,117,108,101,46,78,40,4,0,0,0,117,3,0,0,0, - 115,121,115,117,7,0,0,0,109,111,100,117,108,101,115,117, - 3,0,0,0,105,109,112,117,12,0,0,0,105,110,105,116, - 95,98,117,105,108,116,105,110,40,3,0,0,0,117,3,0, - 0,0,99,108,115,117,8,0,0,0,102,117,108,108,110,97, - 109,101,117,9,0,0,0,105,115,95,114,101,108,111,97,100, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,11,0,0, - 0,108,111,97,100,95,109,111,100,117,108,101,37,1,0,0, - 115,14,0,0,0,0,6,15,1,3,1,17,1,3,1,22, - 1,13,1,117,27,0,0,0,66,117,105,108,116,105,110,73, - 109,112,111,114,116,101,114,46,108,111,97,100,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, - 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,0, - 83,40,2,0,0,0,117,57,0,0,0,82,101,116,117,114, - 110,32,78,111,110,101,32,97,115,32,98,117,105,108,116,45, - 105,110,32,109,111,100,117,108,101,115,32,100,111,32,110,111, - 116,32,104,97,118,101,32,99,111,100,101,32,111,98,106,101, - 99,116,115,46,78,40,1,0,0,0,117,4,0,0,0,78, - 111,110,101,40,2,0,0,0,117,3,0,0,0,99,108,115, - 117,8,0,0,0,102,117,108,108,110,97,109,101,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,8,0,0,0,103,101, - 116,95,99,111,100,101,51,1,0,0,115,2,0,0,0,0, - 4,117,24,0,0,0,66,117,105,108,116,105,110,73,109,112, - 111,114,116,101,114,46,103,101,116,95,99,111,100,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, - 0,0,0,115,4,0,0,0,100,1,0,83,40,2,0,0, - 0,117,56,0,0,0,82,101,116,117,114,110,32,78,111,110, - 101,32,97,115,32,98,117,105,108,116,45,105,110,32,109,111, - 100,117,108,101,115,32,100,111,32,110,111,116,32,104,97,118, - 101,32,115,111,117,114,99,101,32,99,111,100,101,46,78,40, + 115,116,114,97,112,62,117,11,0,0,0,108,111,97,100,95, + 109,111,100,117,108,101,47,1,0,0,115,14,0,0,0,0, + 6,15,1,3,1,17,1,3,1,22,1,13,1,117,27,0, + 0,0,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 114,46,108,111,97,100,95,109,111,100,117,108,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,115,4,0,0,0,100,1,0,83,40,2,0,0,0, + 117,57,0,0,0,82,101,116,117,114,110,32,78,111,110,101, + 32,97,115,32,98,117,105,108,116,45,105,110,32,109,111,100, + 117,108,101,115,32,100,111,32,110,111,116,32,104,97,118,101, + 32,99,111,100,101,32,111,98,106,101,99,116,115,46,78,40, 1,0,0,0,117,4,0,0,0,78,111,110,101,40,2,0, 0,0,117,3,0,0,0,99,108,115,117,8,0,0,0,102, 117,108,108,110,97,109,101,40,0,0,0,0,40,0,0,0, 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,10,0,0,0,103,101,116,95,115,111,117,114, - 99,101,57,1,0,0,115,2,0,0,0,0,4,117,26,0, - 0,0,66,117,105,108,116,105,110,73,109,112,111,114,116,101, - 114,46,103,101,116,95,115,111,117,114,99,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,100,1,0,83,40,2,0,0,0,117, - 51,0,0,0,82,101,116,117,114,110,32,78,111,110,101,32, - 97,115,32,98,117,105,108,116,45,105,110,32,109,111,100,117, - 108,101,115,32,97,114,101,32,110,101,118,101,114,32,112,97, - 99,107,97,103,101,115,46,70,40,1,0,0,0,117,5,0, - 0,0,70,97,108,115,101,40,2,0,0,0,117,3,0,0, + 97,112,62,117,8,0,0,0,103,101,116,95,99,111,100,101, + 61,1,0,0,115,2,0,0,0,0,4,117,24,0,0,0, + 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,46, + 103,101,116,95,99,111,100,101,99,2,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,115,4,0, + 0,0,100,1,0,83,40,2,0,0,0,117,56,0,0,0, + 82,101,116,117,114,110,32,78,111,110,101,32,97,115,32,98, + 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,32, + 100,111,32,110,111,116,32,104,97,118,101,32,115,111,117,114, + 99,101,32,99,111,100,101,46,78,40,1,0,0,0,117,4, + 0,0,0,78,111,110,101,40,2,0,0,0,117,3,0,0, 0,99,108,115,117,8,0,0,0,102,117,108,108,110,97,109, 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, 98,46,95,98,111,111,116,115,116,114,97,112,62,117,10,0, - 0,0,105,115,95,112,97,99,107,97,103,101,63,1,0,0, + 0,0,103,101,116,95,115,111,117,114,99,101,67,1,0,0, 115,2,0,0,0,0,4,117,26,0,0,0,66,117,105,108, - 116,105,110,73,109,112,111,114,116,101,114,46,105,115,95,112, - 97,99,107,97,103,101,78,40,14,0,0,0,117,8,0,0, - 0,95,95,110,97,109,101,95,95,117,10,0,0,0,95,95, - 109,111,100,117,108,101,95,95,117,12,0,0,0,95,95,113, - 117,97,108,110,97,109,101,95,95,117,7,0,0,0,95,95, - 100,111,99,95,95,117,11,0,0,0,99,108,97,115,115,109, - 101,116,104,111,100,117,4,0,0,0,78,111,110,101,117,11, - 0,0,0,102,105,110,100,95,109,111,100,117,108,101,117,11, - 0,0,0,115,101,116,95,112,97,99,107,97,103,101,117,10, - 0,0,0,115,101,116,95,108,111,97,100,101,114,117,17,0, - 0,0,95,114,101,113,117,105,114,101,115,95,98,117,105,108, - 116,105,110,117,11,0,0,0,108,111,97,100,95,109,111,100, - 117,108,101,117,8,0,0,0,103,101,116,95,99,111,100,101, - 117,10,0,0,0,103,101,116,95,115,111,117,114,99,101,117, - 10,0,0,0,105,115,95,112,97,99,107,97,103,101,40,1, - 0,0,0,117,10,0,0,0,95,95,108,111,99,97,108,115, - 95,95,40,0,0,0,0,40,0,0,0,0,117,29,0,0, - 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,15, - 0,0,0,66,117,105,108,116,105,110,73,109,112,111,114,116, - 101,114,17,1,0,0,115,26,0,0,0,16,7,6,2,3, - 1,18,10,3,1,3,1,3,1,27,11,3,1,21,5,3, - 1,21,5,3,1,117,15,0,0,0,66,117,105,108,116,105, - 110,73,109,112,111,114,116,101,114,99,1,0,0,0,0,0, - 0,0,1,0,0,0,6,0,0,0,66,0,0,0,115,155, - 0,0,0,124,0,0,69,101,0,0,90,1,0,100,0,0, - 90,2,0,100,1,0,90,3,0,101,4,0,100,12,0,100, - 2,0,100,3,0,132,1,0,131,1,0,90,6,0,101,4, - 0,101,7,0,101,8,0,101,9,0,100,4,0,100,5,0, - 132,0,0,131,1,0,131,1,0,131,1,0,131,1,0,90, - 10,0,101,4,0,101,9,0,100,6,0,100,7,0,132,0, - 0,131,1,0,131,1,0,90,11,0,101,4,0,101,9,0, - 100,8,0,100,9,0,132,0,0,131,1,0,131,1,0,90, - 12,0,101,4,0,101,9,0,100,10,0,100,11,0,132,0, - 0,131,1,0,131,1,0,90,13,0,100,12,0,83,40,13, - 0,0,0,117,14,0,0,0,70,114,111,122,101,110,73,109, - 112,111,114,116,101,114,117,142,0,0,0,77,101,116,97,32, - 112,97,116,104,32,105,109,112,111,114,116,32,102,111,114,32, - 102,114,111,122,101,110,32,109,111,100,117,108,101,115,46,10, - 10,32,32,32,32,65,108,108,32,109,101,116,104,111,100,115, - 32,97,114,101,32,101,105,116,104,101,114,32,99,108,97,115, - 115,32,111,114,32,115,116,97,116,105,99,32,109,101,116,104, - 111,100,115,32,116,111,32,97,118,111,105,100,32,116,104,101, - 32,110,101,101,100,32,116,111,10,32,32,32,32,105,110,115, - 116,97,110,116,105,97,116,101,32,116,104,101,32,99,108,97, - 115,115,46,10,10,32,32,32,32,99,3,0,0,0,0,0, - 0,0,3,0,0,0,2,0,0,0,67,0,0,0,115,23, - 0,0,0,116,0,0,106,1,0,124,1,0,131,1,0,114, - 19,0,124,0,0,83,100,1,0,83,40,2,0,0,0,117, - 21,0,0,0,70,105,110,100,32,97,32,102,114,111,122,101, - 110,32,109,111,100,117,108,101,46,78,40,3,0,0,0,117, - 3,0,0,0,105,109,112,117,9,0,0,0,105,115,95,102, - 114,111,122,101,110,117,4,0,0,0,78,111,110,101,40,3, - 0,0,0,117,3,0,0,0,99,108,115,117,8,0,0,0, - 102,117,108,108,110,97,109,101,117,4,0,0,0,112,97,116, - 104,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,11,0, - 0,0,102,105,110,100,95,109,111,100,117,108,101,79,1,0, - 0,115,2,0,0,0,0,3,117,26,0,0,0,70,114,111, - 122,101,110,73,109,112,111,114,116,101,114,46,102,105,110,100, - 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, - 3,0,0,0,9,0,0,0,67,0,0,0,115,85,0,0, - 0,124,1,0,116,0,0,106,1,0,107,6,0,125,2,0, - 121,17,0,116,2,0,106,3,0,124,1,0,131,1,0,83, - 87,110,46,0,1,1,1,124,2,0,12,114,73,0,124,1, - 0,116,0,0,106,1,0,107,6,0,114,73,0,116,0,0, - 106,1,0,124,1,0,61,110,0,0,130,0,0,89,110,1, - 0,88,100,1,0,83,40,2,0,0,0,117,21,0,0,0, - 76,111,97,100,32,97,32,102,114,111,122,101,110,32,109,111, - 100,117,108,101,46,78,40,4,0,0,0,117,3,0,0,0, - 115,121,115,117,7,0,0,0,109,111,100,117,108,101,115,117, - 3,0,0,0,105,109,112,117,11,0,0,0,105,110,105,116, - 95,102,114,111,122,101,110,40,3,0,0,0,117,3,0,0, - 0,99,108,115,117,8,0,0,0,102,117,108,108,110,97,109, - 101,117,9,0,0,0,105,115,95,114,101,108,111,97,100,40, - 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, - 108,111,97,100,95,109,111,100,117,108,101,84,1,0,0,115, - 14,0,0,0,0,6,15,1,3,1,17,1,3,1,22,1, - 13,1,117,26,0,0,0,70,114,111,122,101,110,73,109,112, - 111,114,116,101,114,46,108,111,97,100,95,109,111,100,117,108, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,2,0, - 0,0,67,0,0,0,115,13,0,0,0,116,0,0,106,1, - 0,124,1,0,131,1,0,83,40,1,0,0,0,117,45,0, - 0,0,82,101,116,117,114,110,32,116,104,101,32,99,111,100, - 101,32,111,98,106,101,99,116,32,102,111,114,32,116,104,101, - 32,102,114,111,122,101,110,32,109,111,100,117,108,101,46,40, - 2,0,0,0,117,3,0,0,0,105,109,112,117,17,0,0, - 0,103,101,116,95,102,114,111,122,101,110,95,111,98,106,101, - 99,116,40,2,0,0,0,117,3,0,0,0,99,108,115,117, + 116,105,110,73,109,112,111,114,116,101,114,46,103,101,116,95, + 115,111,117,114,99,101,99,2,0,0,0,0,0,0,0,2, + 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, + 100,1,0,83,40,2,0,0,0,117,51,0,0,0,82,101, + 116,117,114,110,32,78,111,110,101,32,97,115,32,98,117,105, + 108,116,45,105,110,32,109,111,100,117,108,101,115,32,97,114, + 101,32,110,101,118,101,114,32,112,97,99,107,97,103,101,115, + 46,70,40,1,0,0,0,117,5,0,0,0,70,97,108,115, + 101,40,2,0,0,0,117,3,0,0,0,99,108,115,117,8, + 0,0,0,102,117,108,108,110,97,109,101,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,10,0,0,0,105,115,95,112, + 97,99,107,97,103,101,73,1,0,0,115,2,0,0,0,0, + 4,117,26,0,0,0,66,117,105,108,116,105,110,73,109,112, + 111,114,116,101,114,46,105,115,95,112,97,99,107,97,103,101, + 78,40,14,0,0,0,117,8,0,0,0,95,95,110,97,109, + 101,95,95,117,10,0,0,0,95,95,109,111,100,117,108,101, + 95,95,117,12,0,0,0,95,95,113,117,97,108,110,97,109, + 101,95,95,117,7,0,0,0,95,95,100,111,99,95,95,117, + 11,0,0,0,99,108,97,115,115,109,101,116,104,111,100,117, + 4,0,0,0,78,111,110,101,117,11,0,0,0,102,105,110, + 100,95,109,111,100,117,108,101,117,11,0,0,0,115,101,116, + 95,112,97,99,107,97,103,101,117,10,0,0,0,115,101,116, + 95,108,111,97,100,101,114,117,17,0,0,0,95,114,101,113, + 117,105,114,101,115,95,98,117,105,108,116,105,110,117,11,0, + 0,0,108,111,97,100,95,109,111,100,117,108,101,117,8,0, + 0,0,103,101,116,95,99,111,100,101,117,10,0,0,0,103, + 101,116,95,115,111,117,114,99,101,117,10,0,0,0,105,115, + 95,112,97,99,107,97,103,101,40,1,0,0,0,117,10,0, + 0,0,95,95,108,111,99,97,108,115,95,95,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,15,0,0,0,66,117,105, + 108,116,105,110,73,109,112,111,114,116,101,114,27,1,0,0, + 115,26,0,0,0,16,7,6,2,3,1,18,10,3,1,3, + 1,3,1,27,11,3,1,21,5,3,1,21,5,3,1,117, + 15,0,0,0,66,117,105,108,116,105,110,73,109,112,111,114, + 116,101,114,99,1,0,0,0,0,0,0,0,1,0,0,0, + 6,0,0,0,66,0,0,0,115,155,0,0,0,124,0,0, + 69,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, + 90,3,0,101,4,0,100,12,0,100,2,0,100,3,0,132, + 1,0,131,1,0,90,6,0,101,4,0,101,7,0,101,8, + 0,101,9,0,100,4,0,100,5,0,132,0,0,131,1,0, + 131,1,0,131,1,0,131,1,0,90,10,0,101,4,0,101, + 9,0,100,6,0,100,7,0,132,0,0,131,1,0,131,1, + 0,90,11,0,101,4,0,101,9,0,100,8,0,100,9,0, + 132,0,0,131,1,0,131,1,0,90,12,0,101,4,0,101, + 9,0,100,10,0,100,11,0,132,0,0,131,1,0,131,1, + 0,90,13,0,100,12,0,83,40,13,0,0,0,117,14,0, + 0,0,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 117,142,0,0,0,77,101,116,97,32,112,97,116,104,32,105, + 109,112,111,114,116,32,102,111,114,32,102,114,111,122,101,110, + 32,109,111,100,117,108,101,115,46,10,10,32,32,32,32,65, + 108,108,32,109,101,116,104,111,100,115,32,97,114,101,32,101, + 105,116,104,101,114,32,99,108,97,115,115,32,111,114,32,115, + 116,97,116,105,99,32,109,101,116,104,111,100,115,32,116,111, + 32,97,118,111,105,100,32,116,104,101,32,110,101,101,100,32, + 116,111,10,32,32,32,32,105,110,115,116,97,110,116,105,97, + 116,101,32,116,104,101,32,99,108,97,115,115,46,10,10,32, + 32,32,32,99,3,0,0,0,0,0,0,0,3,0,0,0, + 2,0,0,0,67,0,0,0,115,23,0,0,0,116,0,0, + 106,1,0,124,1,0,131,1,0,114,19,0,124,0,0,83, + 100,1,0,83,40,2,0,0,0,117,21,0,0,0,70,105, + 110,100,32,97,32,102,114,111,122,101,110,32,109,111,100,117, + 108,101,46,78,40,3,0,0,0,117,4,0,0,0,95,105, + 109,112,117,9,0,0,0,105,115,95,102,114,111,122,101,110, + 117,4,0,0,0,78,111,110,101,40,3,0,0,0,117,3, + 0,0,0,99,108,115,117,8,0,0,0,102,117,108,108,110, + 97,109,101,117,4,0,0,0,112,97,116,104,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,11,0,0,0,102,105,110, + 100,95,109,111,100,117,108,101,89,1,0,0,115,2,0,0, + 0,0,3,117,26,0,0,0,70,114,111,122,101,110,73,109, + 112,111,114,116,101,114,46,102,105,110,100,95,109,111,100,117, + 108,101,99,2,0,0,0,0,0,0,0,3,0,0,0,9, + 0,0,0,67,0,0,0,115,85,0,0,0,124,1,0,116, + 0,0,106,1,0,107,6,0,125,2,0,121,17,0,116,2, + 0,106,3,0,124,1,0,131,1,0,83,87,110,46,0,1, + 1,1,124,2,0,12,114,73,0,124,1,0,116,0,0,106, + 1,0,107,6,0,114,73,0,116,0,0,106,1,0,124,1, + 0,61,110,0,0,130,0,0,89,110,1,0,88,100,1,0, + 83,40,2,0,0,0,117,21,0,0,0,76,111,97,100,32, + 97,32,102,114,111,122,101,110,32,109,111,100,117,108,101,46, + 78,40,4,0,0,0,117,3,0,0,0,115,121,115,117,7, + 0,0,0,109,111,100,117,108,101,115,117,4,0,0,0,95, + 105,109,112,117,11,0,0,0,105,110,105,116,95,102,114,111, + 122,101,110,40,3,0,0,0,117,3,0,0,0,99,108,115, + 117,8,0,0,0,102,117,108,108,110,97,109,101,117,9,0, + 0,0,105,115,95,114,101,108,111,97,100,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,11,0,0,0,108,111,97,100, + 95,109,111,100,117,108,101,94,1,0,0,115,14,0,0,0, + 0,6,15,1,3,1,17,1,3,1,22,1,13,1,117,26, + 0,0,0,70,114,111,122,101,110,73,109,112,111,114,116,101, + 114,46,108,111,97,100,95,109,111,100,117,108,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,2,0,0,0,67,0, + 0,0,115,13,0,0,0,116,0,0,106,1,0,124,1,0, + 131,1,0,83,40,1,0,0,0,117,45,0,0,0,82,101, + 116,117,114,110,32,116,104,101,32,99,111,100,101,32,111,98, + 106,101,99,116,32,102,111,114,32,116,104,101,32,102,114,111, + 122,101,110,32,109,111,100,117,108,101,46,40,2,0,0,0, + 117,4,0,0,0,95,105,109,112,117,17,0,0,0,103,101, + 116,95,102,114,111,122,101,110,95,111,98,106,101,99,116,40, + 2,0,0,0,117,3,0,0,0,99,108,115,117,8,0,0, + 0,102,117,108,108,110,97,109,101,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,8,0,0,0,103,101,116,95,99,111, + 100,101,108,1,0,0,115,2,0,0,0,0,4,117,23,0, + 0,0,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 46,103,101,116,95,99,111,100,101,99,2,0,0,0,0,0, + 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, + 0,0,0,100,1,0,83,40,2,0,0,0,117,54,0,0, + 0,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,115,32,100, + 111,32,110,111,116,32,104,97,118,101,32,115,111,117,114,99, + 101,32,99,111,100,101,46,78,40,1,0,0,0,117,4,0, + 0,0,78,111,110,101,40,2,0,0,0,117,3,0,0,0, + 99,108,115,117,8,0,0,0,102,117,108,108,110,97,109,101, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, + 0,103,101,116,95,115,111,117,114,99,101,114,1,0,0,115, + 2,0,0,0,0,4,117,25,0,0,0,70,114,111,122,101, + 110,73,109,112,111,114,116,101,114,46,103,101,116,95,115,111, + 117,114,99,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,2,0,0,0,67,0,0,0,115,13,0,0,0,116,0, + 0,106,1,0,124,1,0,131,1,0,83,40,1,0,0,0, + 117,41,0,0,0,82,101,116,117,114,110,32,105,102,32,116, + 104,101,32,102,114,111,122,101,110,32,109,111,100,117,108,101, + 32,105,115,32,97,32,112,97,99,107,97,103,101,46,40,2, + 0,0,0,117,4,0,0,0,95,105,109,112,117,17,0,0, + 0,105,115,95,102,114,111,122,101,110,95,112,97,99,107,97, + 103,101,40,2,0,0,0,117,3,0,0,0,99,108,115,117, 8,0,0,0,102,117,108,108,110,97,109,101,40,0,0,0, 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, - 111,116,115,116,114,97,112,62,117,8,0,0,0,103,101,116, - 95,99,111,100,101,98,1,0,0,115,2,0,0,0,0,4, - 117,23,0,0,0,70,114,111,122,101,110,73,109,112,111,114, - 116,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,100,1,0,83,40,2,0,0,0,117, - 54,0,0,0,82,101,116,117,114,110,32,78,111,110,101,32, - 97,115,32,102,114,111,122,101,110,32,109,111,100,117,108,101, - 115,32,100,111,32,110,111,116,32,104,97,118,101,32,115,111, - 117,114,99,101,32,99,111,100,101,46,78,40,1,0,0,0, - 117,4,0,0,0,78,111,110,101,40,2,0,0,0,117,3, - 0,0,0,99,108,115,117,8,0,0,0,102,117,108,108,110, - 97,109,101,40,0,0,0,0,40,0,0,0,0,117,29,0, - 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, - 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 10,0,0,0,103,101,116,95,115,111,117,114,99,101,104,1, - 0,0,115,2,0,0,0,0,4,117,25,0,0,0,70,114, - 111,122,101,110,73,109,112,111,114,116,101,114,46,103,101,116, - 95,115,111,117,114,99,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,2,0,0,0,67,0,0,0,115,13,0,0, - 0,116,0,0,106,1,0,124,1,0,131,1,0,83,40,1, - 0,0,0,117,41,0,0,0,82,101,116,117,114,110,32,105, - 102,32,116,104,101,32,102,114,111,122,101,110,32,109,111,100, - 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, - 46,40,2,0,0,0,117,3,0,0,0,105,109,112,117,17, - 0,0,0,105,115,95,102,114,111,122,101,110,95,112,97,99, - 107,97,103,101,40,2,0,0,0,117,3,0,0,0,99,108, - 115,117,8,0,0,0,102,117,108,108,110,97,109,101,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,105, - 115,95,112,97,99,107,97,103,101,110,1,0,0,115,2,0, - 0,0,0,4,117,25,0,0,0,70,114,111,122,101,110,73, - 109,112,111,114,116,101,114,46,105,115,95,112,97,99,107,97, - 103,101,78,40,14,0,0,0,117,8,0,0,0,95,95,110, - 97,109,101,95,95,117,10,0,0,0,95,95,109,111,100,117, - 108,101,95,95,117,12,0,0,0,95,95,113,117,97,108,110, - 97,109,101,95,95,117,7,0,0,0,95,95,100,111,99,95, - 95,117,11,0,0,0,99,108,97,115,115,109,101,116,104,111, - 100,117,4,0,0,0,78,111,110,101,117,11,0,0,0,102, - 105,110,100,95,109,111,100,117,108,101,117,11,0,0,0,115, - 101,116,95,112,97,99,107,97,103,101,117,10,0,0,0,115, - 101,116,95,108,111,97,100,101,114,117,16,0,0,0,95,114, - 101,113,117,105,114,101,115,95,102,114,111,122,101,110,117,11, - 0,0,0,108,111,97,100,95,109,111,100,117,108,101,117,8, - 0,0,0,103,101,116,95,99,111,100,101,117,10,0,0,0, - 103,101,116,95,115,111,117,114,99,101,117,10,0,0,0,105, - 115,95,112,97,99,107,97,103,101,40,1,0,0,0,117,10, - 0,0,0,95,95,108,111,99,97,108,115,95,95,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,14,0,0,0,70,114, - 111,122,101,110,73,109,112,111,114,116,101,114,70,1,0,0, - 115,26,0,0,0,16,7,6,2,3,1,18,4,3,1,3, - 1,3,1,27,11,3,1,21,5,3,1,21,5,3,1,117, - 14,0,0,0,70,114,111,122,101,110,73,109,112,111,114,116, - 101,114,99,1,0,0,0,0,0,0,0,1,0,0,0,5, - 0,0,0,66,0,0,0,115,74,0,0,0,124,0,0,69, - 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, - 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, - 0,100,5,0,132,0,0,90,5,0,101,6,0,100,6,0, - 100,10,0,100,7,0,100,8,0,132,0,1,131,1,0,90, - 8,0,100,9,0,83,40,11,0,0,0,117,13,0,0,0, - 95,76,111,97,100,101,114,66,97,115,105,99,115,117,84,0, - 0,0,66,97,115,101,32,99,108,97,115,115,32,111,102,32, - 99,111,109,109,111,110,32,99,111,100,101,32,110,101,101,100, - 101,100,32,98,121,32,98,111,116,104,32,83,111,117,114,99, - 101,76,111,97,100,101,114,32,97,110,100,10,32,32,32,32, - 95,83,111,117,114,99,101,108,101,115,115,70,105,108,101,76, - 111,97,100,101,114,46,99,2,0,0,0,0,0,0,0,3, - 0,0,0,3,0,0,0,67,0,0,0,115,54,0,0,0, - 124,0,0,106,0,0,124,1,0,131,1,0,106,1,0,116, - 2,0,131,1,0,100,1,0,25,125,2,0,124,2,0,106, - 3,0,100,2,0,100,3,0,131,2,0,100,4,0,25,100, - 5,0,107,2,0,83,40,6,0,0,0,117,141,0,0,0, - 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, - 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, - 99,116,76,111,97,100,101,114,46,105,115,95,112,97,99,107, - 97,103,101,32,98,121,32,99,104,101,99,107,105,110,103,32, - 105,102,10,32,32,32,32,32,32,32,32,116,104,101,32,112, - 97,116,104,32,114,101,116,117,114,110,101,100,32,98,121,32, - 103,101,116,95,102,105,108,101,110,97,109,101,32,104,97,115, - 32,97,32,102,105,108,101,110,97,109,101,32,111,102,32,39, - 95,95,105,110,105,116,95,95,46,112,121,39,46,105,2,0, - 0,0,117,1,0,0,0,46,105,1,0,0,0,105,0,0, - 0,0,117,8,0,0,0,95,95,105,110,105,116,95,95,40, - 4,0,0,0,117,12,0,0,0,103,101,116,95,102,105,108, - 101,110,97,109,101,117,10,0,0,0,114,112,97,114,116,105, - 116,105,111,110,117,8,0,0,0,112,97,116,104,95,115,101, - 112,117,6,0,0,0,114,115,112,108,105,116,40,3,0,0, + 111,116,115,116,114,97,112,62,117,10,0,0,0,105,115,95, + 112,97,99,107,97,103,101,120,1,0,0,115,2,0,0,0, + 0,4,117,25,0,0,0,70,114,111,122,101,110,73,109,112, + 111,114,116,101,114,46,105,115,95,112,97,99,107,97,103,101, + 78,40,14,0,0,0,117,8,0,0,0,95,95,110,97,109, + 101,95,95,117,10,0,0,0,95,95,109,111,100,117,108,101, + 95,95,117,12,0,0,0,95,95,113,117,97,108,110,97,109, + 101,95,95,117,7,0,0,0,95,95,100,111,99,95,95,117, + 11,0,0,0,99,108,97,115,115,109,101,116,104,111,100,117, + 4,0,0,0,78,111,110,101,117,11,0,0,0,102,105,110, + 100,95,109,111,100,117,108,101,117,11,0,0,0,115,101,116, + 95,112,97,99,107,97,103,101,117,10,0,0,0,115,101,116, + 95,108,111,97,100,101,114,117,16,0,0,0,95,114,101,113, + 117,105,114,101,115,95,102,114,111,122,101,110,117,11,0,0, + 0,108,111,97,100,95,109,111,100,117,108,101,117,8,0,0, + 0,103,101,116,95,99,111,100,101,117,10,0,0,0,103,101, + 116,95,115,111,117,114,99,101,117,10,0,0,0,105,115,95, + 112,97,99,107,97,103,101,40,1,0,0,0,117,10,0,0, + 0,95,95,108,111,99,97,108,115,95,95,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,14,0,0,0,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,80,1,0,0,115,26, + 0,0,0,16,7,6,2,3,1,18,4,3,1,3,1,3, + 1,27,11,3,1,21,5,3,1,21,5,3,1,117,14,0, + 0,0,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, + 0,66,0,0,0,115,74,0,0,0,124,0,0,69,101,0, + 0,90,1,0,100,0,0,90,2,0,100,1,0,90,3,0, + 100,2,0,100,3,0,132,0,0,90,4,0,100,4,0,100, + 5,0,132,0,0,90,5,0,101,6,0,100,6,0,100,10, + 0,100,7,0,100,8,0,132,0,1,131,1,0,90,8,0, + 100,9,0,83,40,11,0,0,0,117,13,0,0,0,95,76, + 111,97,100,101,114,66,97,115,105,99,115,117,84,0,0,0, + 66,97,115,101,32,99,108,97,115,115,32,111,102,32,99,111, + 109,109,111,110,32,99,111,100,101,32,110,101,101,100,101,100, + 32,98,121,32,98,111,116,104,32,83,111,117,114,99,101,76, + 111,97,100,101,114,32,97,110,100,10,32,32,32,32,95,83, + 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, + 100,101,114,46,99,2,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,67,0,0,0,115,54,0,0,0,124,0, + 0,106,0,0,124,1,0,131,1,0,106,1,0,116,2,0, + 131,1,0,100,1,0,25,125,2,0,124,2,0,106,3,0, + 100,2,0,100,3,0,131,2,0,100,4,0,25,100,5,0, + 107,2,0,83,40,6,0,0,0,117,141,0,0,0,67,111, + 110,99,114,101,116,101,32,105,109,112,108,101,109,101,110,116, + 97,116,105,111,110,32,111,102,32,73,110,115,112,101,99,116, + 76,111,97,100,101,114,46,105,115,95,112,97,99,107,97,103, + 101,32,98,121,32,99,104,101,99,107,105,110,103,32,105,102, + 10,32,32,32,32,32,32,32,32,116,104,101,32,112,97,116, + 104,32,114,101,116,117,114,110,101,100,32,98,121,32,103,101, + 116,95,102,105,108,101,110,97,109,101,32,104,97,115,32,97, + 32,102,105,108,101,110,97,109,101,32,111,102,32,39,95,95, + 105,110,105,116,95,95,46,112,121,39,46,105,2,0,0,0, + 117,1,0,0,0,46,105,1,0,0,0,105,0,0,0,0, + 117,8,0,0,0,95,95,105,110,105,116,95,95,40,4,0, + 0,0,117,12,0,0,0,103,101,116,95,102,105,108,101,110, + 97,109,101,117,10,0,0,0,114,112,97,114,116,105,116,105, + 111,110,117,8,0,0,0,112,97,116,104,95,115,101,112,117, + 6,0,0,0,114,115,112,108,105,116,40,3,0,0,0,117, + 4,0,0,0,115,101,108,102,117,8,0,0,0,102,117,108, + 108,110,97,109,101,117,8,0,0,0,102,105,108,101,110,97, + 109,101,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,10, + 0,0,0,105,115,95,112,97,99,107,97,103,101,132,1,0, + 0,115,4,0,0,0,0,3,28,1,117,24,0,0,0,95, + 76,111,97,100,101,114,66,97,115,105,99,115,46,105,115,95, + 112,97,99,107,97,103,101,99,5,0,0,0,0,0,0,0, + 11,0,0,0,23,0,0,0,67,0,0,0,115,213,1,0, + 0,124,2,0,100,1,0,100,2,0,133,2,0,25,125,5, + 0,124,2,0,100,2,0,100,3,0,133,2,0,25,125,6, + 0,124,2,0,100,3,0,100,4,0,133,2,0,25,125,7, + 0,116,0,0,124,5,0,131,1,0,100,2,0,107,3,0, + 115,84,0,124,5,0,116,1,0,106,2,0,131,0,0,107, + 3,0,114,120,0,116,3,0,100,5,0,106,4,0,124,1, + 0,131,1,0,100,6,0,124,1,0,100,7,0,124,3,0, + 131,1,2,130,1,0,110,116,0,116,0,0,124,6,0,131, + 1,0,100,2,0,107,3,0,114,178,0,100,8,0,106,4, + 0,124,1,0,131,1,0,125,8,0,116,5,0,124,8,0, + 131,1,0,1,116,6,0,124,8,0,131,1,0,130,1,0, + 110,58,0,116,0,0,124,7,0,131,1,0,100,2,0,107, + 3,0,114,236,0,100,9,0,106,4,0,124,1,0,131,1, + 0,125,8,0,116,5,0,124,8,0,131,1,0,1,116,6, + 0,124,8,0,131,1,0,130,1,0,110,0,0,124,4,0, + 100,1,0,107,9,0,114,199,1,121,20,0,116,8,0,124, + 4,0,100,10,0,25,131,1,0,125,9,0,87,110,18,0, + 4,116,9,0,107,10,0,114,32,1,1,1,1,89,110,71, + 0,88,116,10,0,124,6,0,131,1,0,124,9,0,107,3, + 0,114,103,1,100,11,0,106,4,0,124,1,0,131,1,0, + 125,8,0,116,5,0,124,8,0,131,1,0,1,116,3,0, + 124,8,0,100,6,0,124,1,0,100,7,0,124,3,0,131, + 1,2,130,1,0,110,0,0,121,18,0,124,4,0,100,12, + 0,25,100,13,0,64,125,10,0,87,110,18,0,4,116,9, + 0,107,10,0,114,141,1,1,1,1,89,113,199,1,88,116, + 10,0,124,7,0,131,1,0,124,10,0,107,3,0,114,199, + 1,116,3,0,100,11,0,106,4,0,124,1,0,131,1,0, + 100,6,0,124,1,0,100,7,0,124,3,0,131,1,2,130, + 1,0,113,199,1,110,0,0,124,2,0,100,4,0,100,1, + 0,133,2,0,25,83,40,14,0,0,0,117,193,0,0,0, + 82,101,116,117,114,110,32,116,104,101,32,109,97,114,115,104, + 97,108,108,101,100,32,98,121,116,101,115,32,102,114,111,109, + 32,98,121,116,101,99,111,100,101,44,32,118,101,114,105,102, + 121,105,110,103,32,116,104,101,32,109,97,103,105,99,10,32, + 32,32,32,32,32,32,32,110,117,109,98,101,114,44,32,116, + 105,109,101,115,116,97,109,112,32,97,110,100,32,115,111,117, + 114,99,101,32,115,105,122,101,32,97,108,111,110,103,32,116, + 104,101,32,119,97,121,46,10,10,32,32,32,32,32,32,32, + 32,73,102,32,115,111,117,114,99,101,95,115,116,97,116,115, + 32,105,115,32,78,111,110,101,32,116,104,101,110,32,115,107, + 105,112,32,116,104,101,32,116,105,109,101,115,116,97,109,112, + 32,99,104,101,99,107,46,10,10,32,32,32,32,32,32,32, + 32,78,105,4,0,0,0,105,8,0,0,0,105,12,0,0, + 0,117,22,0,0,0,98,97,100,32,109,97,103,105,99,32, + 110,117,109,98,101,114,32,105,110,32,123,125,117,4,0,0, + 0,110,97,109,101,117,4,0,0,0,112,97,116,104,117,19, + 0,0,0,98,97,100,32,116,105,109,101,115,116,97,109,112, + 32,105,110,32,123,125,117,14,0,0,0,98,97,100,32,115, + 105,122,101,32,105,110,32,123,125,117,5,0,0,0,109,116, + 105,109,101,117,24,0,0,0,98,121,116,101,99,111,100,101, + 32,105,115,32,115,116,97,108,101,32,102,111,114,32,123,125, + 117,4,0,0,0,115,105,122,101,73,255,255,255,255,0,0, + 0,0,40,11,0,0,0,117,3,0,0,0,108,101,110,117, + 4,0,0,0,95,105,109,112,117,9,0,0,0,103,101,116, + 95,109,97,103,105,99,117,11,0,0,0,73,109,112,111,114, + 116,69,114,114,111,114,117,6,0,0,0,102,111,114,109,97, + 116,117,15,0,0,0,118,101,114,98,111,115,101,95,109,101, + 115,115,97,103,101,117,8,0,0,0,69,79,70,69,114,114, + 111,114,117,4,0,0,0,78,111,110,101,117,3,0,0,0, + 105,110,116,117,8,0,0,0,75,101,121,69,114,114,111,114, + 117,7,0,0,0,95,114,95,108,111,110,103,40,11,0,0, 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,102, - 117,108,108,110,97,109,101,117,8,0,0,0,102,105,108,101, - 110,97,109,101,40,0,0,0,0,40,0,0,0,0,117,29, - 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,10,0,0,0,105,115,95,112,97,99,107,97,103,101,122, - 1,0,0,115,4,0,0,0,0,3,28,1,117,24,0,0, - 0,95,76,111,97,100,101,114,66,97,115,105,99,115,46,105, - 115,95,112,97,99,107,97,103,101,99,5,0,0,0,0,0, - 0,0,11,0,0,0,23,0,0,0,67,0,0,0,115,213, - 1,0,0,124,2,0,100,1,0,100,2,0,133,2,0,25, - 125,5,0,124,2,0,100,2,0,100,3,0,133,2,0,25, - 125,6,0,124,2,0,100,3,0,100,4,0,133,2,0,25, - 125,7,0,116,0,0,124,5,0,131,1,0,100,2,0,107, - 3,0,115,84,0,124,5,0,116,1,0,106,2,0,131,0, - 0,107,3,0,114,120,0,116,3,0,100,5,0,106,4,0, - 124,1,0,131,1,0,100,6,0,124,1,0,100,7,0,124, - 3,0,131,1,2,130,1,0,110,116,0,116,0,0,124,6, - 0,131,1,0,100,2,0,107,3,0,114,178,0,100,8,0, - 106,4,0,124,1,0,131,1,0,125,8,0,116,5,0,124, - 8,0,131,1,0,1,116,6,0,124,8,0,131,1,0,130, - 1,0,110,58,0,116,0,0,124,7,0,131,1,0,100,2, - 0,107,3,0,114,236,0,100,9,0,106,4,0,124,1,0, - 131,1,0,125,8,0,116,5,0,124,8,0,131,1,0,1, - 116,6,0,124,8,0,131,1,0,130,1,0,110,0,0,124, - 4,0,100,1,0,107,9,0,114,199,1,121,20,0,116,8, - 0,124,4,0,100,10,0,25,131,1,0,125,9,0,87,110, - 18,0,4,116,9,0,107,10,0,114,32,1,1,1,1,89, - 110,71,0,88,116,10,0,124,6,0,131,1,0,124,9,0, - 107,3,0,114,103,1,100,11,0,106,4,0,124,1,0,131, - 1,0,125,8,0,116,5,0,124,8,0,131,1,0,1,116, - 3,0,124,8,0,100,6,0,124,1,0,100,7,0,124,3, - 0,131,1,2,130,1,0,110,0,0,121,18,0,124,4,0, - 100,12,0,25,100,13,0,64,125,10,0,87,110,18,0,4, - 116,9,0,107,10,0,114,141,1,1,1,1,89,113,199,1, - 88,116,10,0,124,7,0,131,1,0,124,10,0,107,3,0, - 114,199,1,116,3,0,100,11,0,106,4,0,124,1,0,131, - 1,0,100,6,0,124,1,0,100,7,0,124,3,0,131,1, - 2,130,1,0,113,199,1,110,0,0,124,2,0,100,4,0, - 100,1,0,133,2,0,25,83,40,14,0,0,0,117,193,0, - 0,0,82,101,116,117,114,110,32,116,104,101,32,109,97,114, - 115,104,97,108,108,101,100,32,98,121,116,101,115,32,102,114, - 111,109,32,98,121,116,101,99,111,100,101,44,32,118,101,114, - 105,102,121,105,110,103,32,116,104,101,32,109,97,103,105,99, - 10,32,32,32,32,32,32,32,32,110,117,109,98,101,114,44, - 32,116,105,109,101,115,116,97,109,112,32,97,110,100,32,115, - 111,117,114,99,101,32,115,105,122,101,32,97,108,111,110,103, - 32,116,104,101,32,119,97,121,46,10,10,32,32,32,32,32, - 32,32,32,73,102,32,115,111,117,114,99,101,95,115,116,97, - 116,115,32,105,115,32,78,111,110,101,32,116,104,101,110,32, - 115,107,105,112,32,116,104,101,32,116,105,109,101,115,116,97, - 109,112,32,99,104,101,99,107,46,10,10,32,32,32,32,32, - 32,32,32,78,105,4,0,0,0,105,8,0,0,0,105,12, - 0,0,0,117,22,0,0,0,98,97,100,32,109,97,103,105, - 99,32,110,117,109,98,101,114,32,105,110,32,123,125,117,4, - 0,0,0,110,97,109,101,117,4,0,0,0,112,97,116,104, - 117,19,0,0,0,98,97,100,32,116,105,109,101,115,116,97, - 109,112,32,105,110,32,123,125,117,14,0,0,0,98,97,100, - 32,115,105,122,101,32,105,110,32,123,125,117,5,0,0,0, - 109,116,105,109,101,117,24,0,0,0,98,121,116,101,99,111, - 100,101,32,105,115,32,115,116,97,108,101,32,102,111,114,32, - 123,125,117,4,0,0,0,115,105,122,101,73,255,255,255,255, - 0,0,0,0,40,11,0,0,0,117,3,0,0,0,108,101, - 110,117,3,0,0,0,105,109,112,117,9,0,0,0,103,101, - 116,95,109,97,103,105,99,117,11,0,0,0,73,109,112,111, - 114,116,69,114,114,111,114,117,6,0,0,0,102,111,114,109, - 97,116,117,15,0,0,0,118,101,114,98,111,115,101,95,109, - 101,115,115,97,103,101,117,8,0,0,0,69,79,70,69,114, - 114,111,114,117,4,0,0,0,78,111,110,101,117,3,0,0, - 0,105,110,116,117,8,0,0,0,75,101,121,69,114,114,111, - 114,117,7,0,0,0,95,114,95,108,111,110,103,40,11,0, - 0,0,117,4,0,0,0,115,101,108,102,117,8,0,0,0, - 102,117,108,108,110,97,109,101,117,4,0,0,0,100,97,116, - 97,117,13,0,0,0,98,121,116,101,99,111,100,101,95,112, - 97,116,104,117,12,0,0,0,115,111,117,114,99,101,95,115, - 116,97,116,115,117,5,0,0,0,109,97,103,105,99,117,13, - 0,0,0,114,97,119,95,116,105,109,101,115,116,97,109,112, - 117,8,0,0,0,114,97,119,95,115,105,122,101,117,7,0, - 0,0,109,101,115,115,97,103,101,117,12,0,0,0,115,111, - 117,114,99,101,95,109,116,105,109,101,117,11,0,0,0,115, - 111,117,114,99,101,95,115,105,122,101,40,0,0,0,0,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,20,0,0,0,95,98,121,116,101, - 115,95,102,114,111,109,95,98,121,116,101,99,111,100,101,128, - 1,0,0,115,66,0,0,0,0,7,16,1,16,1,16,1, - 36,1,18,1,18,1,18,1,15,1,10,1,15,1,18,1, - 15,1,10,1,15,1,12,1,3,1,20,1,13,1,5,2, - 18,1,15,1,10,1,15,1,12,1,3,1,18,1,13,1, - 5,2,18,1,3,1,15,1,21,3,117,34,0,0,0,95, - 76,111,97,100,101,114,66,97,115,105,99,115,46,95,98,121, - 116,101,115,95,102,114,111,109,95,98,121,116,101,99,111,100, - 101,117,10,0,0,0,115,111,117,114,99,101,108,101,115,115, - 99,2,0,0,0,1,0,0,0,5,0,0,0,3,0,0, - 0,67,0,0,0,115,196,0,0,0,124,1,0,106,0,0, - 125,3,0,124,0,0,106,1,0,124,3,0,131,1,0,125, - 4,0,124,0,0,106,2,0,124,3,0,131,1,0,124,1, - 0,95,3,0,124,2,0,115,72,0,116,4,0,106,5,0, - 124,1,0,106,3,0,131,1,0,124,1,0,95,6,0,110, - 12,0,124,1,0,106,3,0,124,1,0,95,6,0,124,3, - 0,124,1,0,95,7,0,124,0,0,106,8,0,124,3,0, - 131,1,0,114,142,0,124,1,0,106,3,0,106,9,0,116, - 10,0,100,1,0,131,2,0,100,2,0,25,103,1,0,124, - 1,0,95,11,0,110,25,0,124,1,0,106,7,0,106,12, - 0,100,3,0,131,1,0,100,2,0,25,124,1,0,95,7, - 0,124,0,0,124,1,0,95,13,0,116,14,0,124,4,0, - 124,1,0,106,15,0,131,2,0,1,124,1,0,83,40,4, - 0,0,0,117,82,0,0,0,72,101,108,112,101,114,32,102, - 111,114,32,108,111,97,100,95,109,111,100,117,108,101,32,97, - 98,108,101,32,116,111,32,104,97,110,100,108,101,32,101,105, - 116,104,101,114,32,115,111,117,114,99,101,32,111,114,32,115, - 111,117,114,99,101,108,101,115,115,10,32,32,32,32,32,32, - 32,32,108,111,97,100,105,110,103,46,105,1,0,0,0,105, - 0,0,0,0,117,1,0,0,0,46,40,16,0,0,0,117, - 8,0,0,0,95,95,110,97,109,101,95,95,117,8,0,0, - 0,103,101,116,95,99,111,100,101,117,12,0,0,0,103,101, - 116,95,102,105,108,101,110,97,109,101,117,8,0,0,0,95, - 95,102,105,108,101,95,95,117,3,0,0,0,105,109,112,117, + 117,108,108,110,97,109,101,117,4,0,0,0,100,97,116,97, + 117,13,0,0,0,98,121,116,101,99,111,100,101,95,112,97, + 116,104,117,12,0,0,0,115,111,117,114,99,101,95,115,116, + 97,116,115,117,5,0,0,0,109,97,103,105,99,117,13,0, + 0,0,114,97,119,95,116,105,109,101,115,116,97,109,112,117, + 8,0,0,0,114,97,119,95,115,105,122,101,117,7,0,0, + 0,109,101,115,115,97,103,101,117,12,0,0,0,115,111,117, + 114,99,101,95,109,116,105,109,101,117,11,0,0,0,115,111, + 117,114,99,101,95,115,105,122,101,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,20,0,0,0,95,98,121,116,101,115, + 95,102,114,111,109,95,98,121,116,101,99,111,100,101,138,1, + 0,0,115,66,0,0,0,0,7,16,1,16,1,16,1,36, + 1,18,1,18,1,18,1,15,1,10,1,15,1,18,1,15, + 1,10,1,15,1,12,1,3,1,20,1,13,1,5,2,18, + 1,15,1,10,1,15,1,12,1,3,1,18,1,13,1,5, + 2,18,1,3,1,15,1,21,3,117,34,0,0,0,95,76, + 111,97,100,101,114,66,97,115,105,99,115,46,95,98,121,116, + 101,115,95,102,114,111,109,95,98,121,116,101,99,111,100,101, + 117,10,0,0,0,115,111,117,114,99,101,108,101,115,115,99, + 2,0,0,0,1,0,0,0,5,0,0,0,3,0,0,0, + 67,0,0,0,115,196,0,0,0,124,1,0,106,0,0,125, + 3,0,124,0,0,106,1,0,124,3,0,131,1,0,125,4, + 0,124,0,0,106,2,0,124,3,0,131,1,0,124,1,0, + 95,3,0,124,2,0,115,72,0,116,4,0,106,5,0,124, + 1,0,106,3,0,131,1,0,124,1,0,95,6,0,110,12, + 0,124,1,0,106,3,0,124,1,0,95,6,0,124,3,0, + 124,1,0,95,7,0,124,0,0,106,8,0,124,3,0,131, + 1,0,114,142,0,124,1,0,106,3,0,106,9,0,116,10, + 0,100,1,0,131,2,0,100,2,0,25,103,1,0,124,1, + 0,95,11,0,110,25,0,124,1,0,106,7,0,106,12,0, + 100,3,0,131,1,0,100,2,0,25,124,1,0,95,7,0, + 124,0,0,124,1,0,95,13,0,116,14,0,124,4,0,124, + 1,0,106,15,0,131,2,0,1,124,1,0,83,40,4,0, + 0,0,117,82,0,0,0,72,101,108,112,101,114,32,102,111, + 114,32,108,111,97,100,95,109,111,100,117,108,101,32,97,98, + 108,101,32,116,111,32,104,97,110,100,108,101,32,101,105,116, + 104,101,114,32,115,111,117,114,99,101,32,111,114,32,115,111, + 117,114,99,101,108,101,115,115,10,32,32,32,32,32,32,32, + 32,108,111,97,100,105,110,103,46,105,1,0,0,0,105,0, + 0,0,0,117,1,0,0,0,46,40,16,0,0,0,117,8, + 0,0,0,95,95,110,97,109,101,95,95,117,8,0,0,0, + 103,101,116,95,99,111,100,101,117,12,0,0,0,103,101,116, + 95,102,105,108,101,110,97,109,101,117,8,0,0,0,95,95, + 102,105,108,101,95,95,117,4,0,0,0,95,105,109,112,117, 17,0,0,0,99,97,99,104,101,95,102,114,111,109,95,115, 111,117,114,99,101,117,10,0,0,0,95,95,99,97,99,104, 101,100,95,95,117,11,0,0,0,95,95,112,97,99,107,97, @@ -1166,7 +1181,7 @@ 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, 111,111,116,115,116,114,97,112,62,117,12,0,0,0,95,108, - 111,97,100,95,109,111,100,117,108,101,173,1,0,0,115,26, + 111,97,100,95,109,111,100,117,108,101,183,1,0,0,115,26, 0,0,0,0,4,9,1,15,1,18,1,6,1,24,2,12, 1,9,1,15,1,34,2,25,1,9,1,16,1,117,26,0, 0,0,95,76,111,97,100,101,114,66,97,115,105,99,115,46, @@ -1185,7 +1200,7 @@ 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, 116,114,97,112,62,117,13,0,0,0,95,76,111,97,100,101, - 114,66,97,115,105,99,115,117,1,0,0,115,10,0,0,0, + 114,66,97,115,105,99,115,127,1,0,0,115,10,0,0,0, 16,3,6,2,12,6,12,45,6,1,117,13,0,0,0,95, 76,111,97,100,101,114,66,97,115,105,99,115,99,1,0,0, 0,0,0,0,0,1,0,0,0,2,0,0,0,66,0,0, @@ -1213,7 +1228,7 @@ 112,97,116,104,40,0,0,0,0,40,0,0,0,0,117,29, 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,10,0,0,0,112,97,116,104,95,109,116,105,109,101,196, + 117,10,0,0,0,112,97,116,104,95,109,116,105,109,101,206, 1,0,0,115,2,0,0,0,0,4,117,23,0,0,0,83, 111,117,114,99,101,76,111,97,100,101,114,46,112,97,116,104, 95,109,116,105,109,101,99,2,0,0,0,0,0,0,0,2, @@ -1250,7 +1265,7 @@ 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, 62,117,10,0,0,0,112,97,116,104,95,115,116,97,116,115, - 202,1,0,0,115,2,0,0,0,0,10,117,23,0,0,0, + 212,1,0,0,115,2,0,0,0,0,10,117,23,0,0,0, 83,111,117,114,99,101,76,111,97,100,101,114,46,112,97,116, 104,95,115,116,97,116,115,99,3,0,0,0,0,0,0,0, 3,0,0,0,1,0,0,0,67,0,0,0,115,10,0,0, @@ -1272,7 +1287,7 @@ 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, 115,116,114,97,112,62,117,8,0,0,0,115,101,116,95,100, - 97,116,97,214,1,0,0,115,2,0,0,0,0,6,117,21, + 97,116,97,224,1,0,0,115,2,0,0,0,0,6,117,21, 0,0,0,83,111,117,114,99,101,76,111,97,100,101,114,46, 115,101,116,95,100,97,116,97,99,2,0,0,0,0,0,0, 0,7,0,0,0,12,0,0,0,67,0,0,0,115,156,0, @@ -1315,7 +1330,7 @@ 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, 97,112,62,117,10,0,0,0,103,101,116,95,115,111,117,114, - 99,101,223,1,0,0,115,20,0,0,0,0,2,12,1,15, + 99,101,233,1,0,0,115,20,0,0,0,0,2,12,1,15, 1,3,1,19,1,13,1,9,1,14,1,27,1,18,1,117, 23,0,0,0,83,111,117,114,99,101,76,111,97,100,101,114, 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, @@ -1377,454 +1392,333 @@ 0,0,100,111,110,116,95,105,110,104,101,114,105,116,117,10, 0,0,0,119,114,111,116,101,32,123,33,114,125,78,84,40, 30,0,0,0,117,12,0,0,0,103,101,116,95,102,105,108, - 101,110,97,109,101,117,3,0,0,0,105,109,112,117,17,0, - 0,0,99,97,99,104,101,95,102,114,111,109,95,115,111,117, - 114,99,101,117,4,0,0,0,78,111,110,101,117,10,0,0, - 0,112,97,116,104,95,115,116,97,116,115,117,19,0,0,0, - 78,111,116,73,109,112,108,101,109,101,110,116,101,100,69,114, - 114,111,114,117,3,0,0,0,105,110,116,117,8,0,0,0, - 103,101,116,95,100,97,116,97,117,7,0,0,0,73,79,69, - 114,114,111,114,117,20,0,0,0,95,98,121,116,101,115,95, - 102,114,111,109,95,98,121,116,101,99,111,100,101,117,11,0, - 0,0,73,109,112,111,114,116,69,114,114,111,114,117,8,0, - 0,0,69,79,70,69,114,114,111,114,117,15,0,0,0,118, - 101,114,98,111,115,101,95,109,101,115,115,97,103,101,117,7, - 0,0,0,109,97,114,115,104,97,108,117,5,0,0,0,108, - 111,97,100,115,117,10,0,0,0,105,115,105,110,115,116,97, - 110,99,101,117,9,0,0,0,99,111,100,101,95,116,121,112, - 101,117,16,0,0,0,95,102,105,120,95,99,111,95,102,105, - 108,101,110,97,109,101,117,6,0,0,0,102,111,114,109,97, - 116,117,7,0,0,0,99,111,109,112,105,108,101,117,4,0, - 0,0,84,114,117,101,117,3,0,0,0,115,121,115,117,19, - 0,0,0,100,111,110,116,95,119,114,105,116,101,95,98,121, - 116,101,99,111,100,101,117,9,0,0,0,98,121,116,101,97, - 114,114,97,121,117,9,0,0,0,103,101,116,95,109,97,103, - 105,99,117,6,0,0,0,101,120,116,101,110,100,117,7,0, - 0,0,95,119,95,108,111,110,103,117,3,0,0,0,108,101, - 110,117,5,0,0,0,100,117,109,112,115,117,8,0,0,0, - 115,101,116,95,100,97,116,97,40,12,0,0,0,117,4,0, - 0,0,115,101,108,102,117,8,0,0,0,102,117,108,108,110, - 97,109,101,117,11,0,0,0,115,111,117,114,99,101,95,112, - 97,116,104,117,13,0,0,0,98,121,116,101,99,111,100,101, - 95,112,97,116,104,117,12,0,0,0,115,111,117,114,99,101, - 95,109,116,105,109,101,117,2,0,0,0,115,116,117,4,0, - 0,0,100,97,116,97,117,10,0,0,0,98,121,116,101,115, - 95,100,97,116,97,117,5,0,0,0,102,111,117,110,100,117, - 3,0,0,0,109,115,103,117,12,0,0,0,115,111,117,114, - 99,101,95,98,121,116,101,115,117,11,0,0,0,99,111,100, - 101,95,111,98,106,101,99,116,40,0,0,0,0,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,8,0,0,0,103,101,116,95,99,111,100, - 101,236,1,0,0,115,92,0,0,0,0,7,15,1,15,1, - 6,1,12,1,3,1,19,1,13,1,5,2,16,1,3,1, - 19,1,13,1,5,2,3,1,12,1,3,1,13,1,19,1, - 5,2,9,1,7,1,15,1,15,1,16,1,6,1,7,1, - 4,2,6,1,18,1,18,1,15,1,15,1,9,1,13,1, - 22,1,12,4,18,1,19,1,25,1,22,1,3,1,16,1, - 17,1,13,1,8,1,117,21,0,0,0,83,111,117,114,99, - 101,76,111,97,100,101,114,46,103,101,116,95,99,111,100,101, - 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, - 0,67,0,0,0,115,13,0,0,0,124,0,0,106,0,0, - 124,1,0,131,1,0,83,40,1,0,0,0,117,0,1,0, - 0,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, - 101,110,116,97,116,105,111,110,32,111,102,32,76,111,97,100, - 101,114,46,108,111,97,100,95,109,111,100,117,108,101,46,10, - 10,32,32,32,32,32,32,32,32,82,101,113,117,105,114,101, - 115,32,69,120,101,99,117,116,105,111,110,76,111,97,100,101, - 114,46,103,101,116,95,102,105,108,101,110,97,109,101,32,97, - 110,100,32,82,101,115,111,117,114,99,101,76,111,97,100,101, - 114,46,103,101,116,95,100,97,116,97,32,116,111,32,98,101, - 10,32,32,32,32,32,32,32,32,105,109,112,108,101,109,101, - 110,116,101,100,32,116,111,32,108,111,97,100,32,115,111,117, - 114,99,101,32,99,111,100,101,46,32,85,115,101,32,111,102, - 32,98,121,116,101,99,111,100,101,32,105,115,32,100,105,99, - 116,97,116,101,100,32,98,121,32,119,104,101,116,104,101,114, - 10,32,32,32,32,32,32,32,32,103,101,116,95,99,111,100, - 101,32,117,115,101,115,47,119,114,105,116,101,115,32,98,121, - 116,101,99,111,100,101,46,10,10,32,32,32,32,32,32,32, - 32,40,1,0,0,0,117,12,0,0,0,95,108,111,97,100, - 95,109,111,100,117,108,101,40,2,0,0,0,117,4,0,0, - 0,115,101,108,102,117,8,0,0,0,102,117,108,108,110,97, - 109,101,40,0,0,0,0,40,0,0,0,0,117,29,0,0, - 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,11, - 0,0,0,108,111,97,100,95,109,111,100,117,108,101,41,2, - 0,0,115,2,0,0,0,0,8,117,24,0,0,0,83,111, - 117,114,99,101,76,111,97,100,101,114,46,108,111,97,100,95, - 109,111,100,117,108,101,78,40,9,0,0,0,117,8,0,0, - 0,95,95,110,97,109,101,95,95,117,10,0,0,0,95,95, - 109,111,100,117,108,101,95,95,117,12,0,0,0,95,95,113, - 117,97,108,110,97,109,101,95,95,117,10,0,0,0,112,97, - 116,104,95,109,116,105,109,101,117,10,0,0,0,112,97,116, - 104,95,115,116,97,116,115,117,8,0,0,0,115,101,116,95, - 100,97,116,97,117,10,0,0,0,103,101,116,95,115,111,117, - 114,99,101,117,8,0,0,0,103,101,116,95,99,111,100,101, - 117,11,0,0,0,108,111,97,100,95,109,111,100,117,108,101, - 40,1,0,0,0,117,10,0,0,0,95,95,108,111,99,97, - 108,115,95,95,40,0,0,0,0,40,0,0,0,0,117,29, - 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,12,0,0,0,83,111,117,114,99,101,76,111,97,100,101, - 114,194,1,0,0,115,12,0,0,0,16,2,12,6,12,12, - 12,9,12,13,12,61,117,12,0,0,0,83,111,117,114,99, - 101,76,111,97,100,101,114,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,66,0,0,0,115,68,0,0, - 0,124,0,0,69,101,0,0,90,1,0,100,0,0,90,2, - 0,100,1,0,90,3,0,100,2,0,100,3,0,132,0,0, - 90,4,0,101,5,0,100,4,0,100,5,0,132,0,0,131, - 1,0,90,6,0,100,6,0,100,7,0,132,0,0,90,7, - 0,100,8,0,83,40,9,0,0,0,117,11,0,0,0,95, - 70,105,108,101,76,111,97,100,101,114,117,103,0,0,0,66, - 97,115,101,32,102,105,108,101,32,108,111,97,100,101,114,32, - 99,108,97,115,115,32,119,104,105,99,104,32,105,109,112,108, - 101,109,101,110,116,115,32,116,104,101,32,108,111,97,100,101, - 114,32,112,114,111,116,111,99,111,108,32,109,101,116,104,111, - 100,115,32,116,104,97,116,10,32,32,32,32,114,101,113,117, - 105,114,101,32,102,105,108,101,32,115,121,115,116,101,109,32, - 117,115,97,103,101,46,99,3,0,0,0,0,0,0,0,3, - 0,0,0,2,0,0,0,67,0,0,0,115,22,0,0,0, - 124,1,0,124,0,0,95,0,0,124,2,0,124,0,0,95, - 1,0,100,1,0,83,40,2,0,0,0,117,75,0,0,0, - 67,97,99,104,101,32,116,104,101,32,109,111,100,117,108,101, - 32,110,97,109,101,32,97,110,100,32,116,104,101,32,112,97, - 116,104,32,116,111,32,116,104,101,32,102,105,108,101,32,102, - 111,117,110,100,32,98,121,32,116,104,101,10,32,32,32,32, - 32,32,32,32,102,105,110,100,101,114,46,78,40,2,0,0, - 0,117,5,0,0,0,95,110,97,109,101,117,5,0,0,0, - 95,112,97,116,104,40,3,0,0,0,117,4,0,0,0,115, - 101,108,102,117,8,0,0,0,102,117,108,108,110,97,109,101, - 117,4,0,0,0,112,97,116,104,40,0,0,0,0,40,0, + 101,110,97,109,101,117,4,0,0,0,95,105,109,112,117,17, + 0,0,0,99,97,99,104,101,95,102,114,111,109,95,115,111, + 117,114,99,101,117,4,0,0,0,78,111,110,101,117,10,0, + 0,0,112,97,116,104,95,115,116,97,116,115,117,19,0,0, + 0,78,111,116,73,109,112,108,101,109,101,110,116,101,100,69, + 114,114,111,114,117,3,0,0,0,105,110,116,117,8,0,0, + 0,103,101,116,95,100,97,116,97,117,7,0,0,0,73,79, + 69,114,114,111,114,117,20,0,0,0,95,98,121,116,101,115, + 95,102,114,111,109,95,98,121,116,101,99,111,100,101,117,11, + 0,0,0,73,109,112,111,114,116,69,114,114,111,114,117,8, + 0,0,0,69,79,70,69,114,114,111,114,117,15,0,0,0, + 118,101,114,98,111,115,101,95,109,101,115,115,97,103,101,117, + 7,0,0,0,109,97,114,115,104,97,108,117,5,0,0,0, + 108,111,97,100,115,117,10,0,0,0,105,115,105,110,115,116, + 97,110,99,101,117,9,0,0,0,99,111,100,101,95,116,121, + 112,101,117,16,0,0,0,95,102,105,120,95,99,111,95,102, + 105,108,101,110,97,109,101,117,6,0,0,0,102,111,114,109, + 97,116,117,7,0,0,0,99,111,109,112,105,108,101,117,4, + 0,0,0,84,114,117,101,117,3,0,0,0,115,121,115,117, + 19,0,0,0,100,111,110,116,95,119,114,105,116,101,95,98, + 121,116,101,99,111,100,101,117,9,0,0,0,98,121,116,101, + 97,114,114,97,121,117,9,0,0,0,103,101,116,95,109,97, + 103,105,99,117,6,0,0,0,101,120,116,101,110,100,117,7, + 0,0,0,95,119,95,108,111,110,103,117,3,0,0,0,108, + 101,110,117,5,0,0,0,100,117,109,112,115,117,8,0,0, + 0,115,101,116,95,100,97,116,97,40,12,0,0,0,117,4, + 0,0,0,115,101,108,102,117,8,0,0,0,102,117,108,108, + 110,97,109,101,117,11,0,0,0,115,111,117,114,99,101,95, + 112,97,116,104,117,13,0,0,0,98,121,116,101,99,111,100, + 101,95,112,97,116,104,117,12,0,0,0,115,111,117,114,99, + 101,95,109,116,105,109,101,117,2,0,0,0,115,116,117,4, + 0,0,0,100,97,116,97,117,10,0,0,0,98,121,116,101, + 115,95,100,97,116,97,117,5,0,0,0,102,111,117,110,100, + 117,3,0,0,0,109,115,103,117,12,0,0,0,115,111,117, + 114,99,101,95,98,121,116,101,115,117,11,0,0,0,99,111, + 100,101,95,111,98,106,101,99,116,40,0,0,0,0,40,0, 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,8,0,0,0,95,95,105,110,105,116, - 95,95,57,2,0,0,115,4,0,0,0,0,3,9,1,117, - 20,0,0,0,95,70,105,108,101,76,111,97,100,101,114,46, - 95,95,105,110,105,116,95,95,99,2,0,0,0,0,0,0, - 0,2,0,0,0,1,0,0,0,67,0,0,0,115,7,0, - 0,0,124,0,0,106,0,0,83,40,1,0,0,0,117,58, - 0,0,0,82,101,116,117,114,110,32,116,104,101,32,112,97, - 116,104,32,116,111,32,116,104,101,32,115,111,117,114,99,101, - 32,102,105,108,101,32,97,115,32,102,111,117,110,100,32,98, - 121,32,116,104,101,32,102,105,110,100,101,114,46,40,1,0, - 0,0,117,5,0,0,0,95,112,97,116,104,40,2,0,0, - 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,102, - 117,108,108,110,97,109,101,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,12,0,0,0,103,101,116,95,102,105,108,101, - 110,97,109,101,63,2,0,0,115,2,0,0,0,0,3,117, - 24,0,0,0,95,70,105,108,101,76,111,97,100,101,114,46, - 103,101,116,95,102,105,108,101,110,97,109,101,99,2,0,0, - 0,0,0,0,0,3,0,0,0,8,0,0,0,67,0,0, - 0,115,41,0,0,0,116,0,0,106,1,0,124,1,0,100, - 1,0,131,2,0,143,17,0,125,2,0,124,2,0,106,2, - 0,131,0,0,83,87,100,2,0,81,88,100,2,0,83,40, - 3,0,0,0,117,39,0,0,0,82,101,116,117,114,110,32, - 116,104,101,32,100,97,116,97,32,102,114,111,109,32,112,97, - 116,104,32,97,115,32,114,97,119,32,98,121,116,101,115,46, - 117,1,0,0,0,114,78,40,3,0,0,0,117,3,0,0, - 0,95,105,111,117,6,0,0,0,70,105,108,101,73,79,117, - 4,0,0,0,114,101,97,100,40,3,0,0,0,117,4,0, - 0,0,115,101,108,102,117,4,0,0,0,112,97,116,104,117, - 4,0,0,0,102,105,108,101,40,0,0,0,0,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,8,0,0,0,103,101,116,95,100,97,116, - 97,68,2,0,0,115,4,0,0,0,0,2,21,1,117,20, - 0,0,0,95,70,105,108,101,76,111,97,100,101,114,46,103, - 101,116,95,100,97,116,97,78,40,8,0,0,0,117,8,0, + 116,114,97,112,62,117,8,0,0,0,103,101,116,95,99,111, + 100,101,246,1,0,0,115,92,0,0,0,0,7,15,1,15, + 1,6,1,12,1,3,1,19,1,13,1,5,2,16,1,3, + 1,19,1,13,1,5,2,3,1,12,1,3,1,13,1,19, + 1,5,2,9,1,7,1,15,1,15,1,16,1,6,1,7, + 1,4,2,6,1,18,1,18,1,15,1,15,1,9,1,13, + 1,22,1,12,4,18,1,19,1,25,1,22,1,3,1,16, + 1,17,1,13,1,8,1,117,21,0,0,0,83,111,117,114, + 99,101,76,111,97,100,101,114,46,103,101,116,95,99,111,100, + 101,99,2,0,0,0,0,0,0,0,2,0,0,0,2,0, + 0,0,67,0,0,0,115,13,0,0,0,124,0,0,106,0, + 0,124,1,0,131,1,0,83,40,1,0,0,0,117,0,1, + 0,0,67,111,110,99,114,101,116,101,32,105,109,112,108,101, + 109,101,110,116,97,116,105,111,110,32,111,102,32,76,111,97, + 100,101,114,46,108,111,97,100,95,109,111,100,117,108,101,46, + 10,10,32,32,32,32,32,32,32,32,82,101,113,117,105,114, + 101,115,32,69,120,101,99,117,116,105,111,110,76,111,97,100, + 101,114,46,103,101,116,95,102,105,108,101,110,97,109,101,32, + 97,110,100,32,82,101,115,111,117,114,99,101,76,111,97,100, + 101,114,46,103,101,116,95,100,97,116,97,32,116,111,32,98, + 101,10,32,32,32,32,32,32,32,32,105,109,112,108,101,109, + 101,110,116,101,100,32,116,111,32,108,111,97,100,32,115,111, + 117,114,99,101,32,99,111,100,101,46,32,85,115,101,32,111, + 102,32,98,121,116,101,99,111,100,101,32,105,115,32,100,105, + 99,116,97,116,101,100,32,98,121,32,119,104,101,116,104,101, + 114,10,32,32,32,32,32,32,32,32,103,101,116,95,99,111, + 100,101,32,117,115,101,115,47,119,114,105,116,101,115,32,98, + 121,116,101,99,111,100,101,46,10,10,32,32,32,32,32,32, + 32,32,40,1,0,0,0,117,12,0,0,0,95,108,111,97, + 100,95,109,111,100,117,108,101,40,2,0,0,0,117,4,0, + 0,0,115,101,108,102,117,8,0,0,0,102,117,108,108,110, + 97,109,101,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 11,0,0,0,108,111,97,100,95,109,111,100,117,108,101,51, + 2,0,0,115,2,0,0,0,0,8,117,24,0,0,0,83, + 111,117,114,99,101,76,111,97,100,101,114,46,108,111,97,100, + 95,109,111,100,117,108,101,78,40,9,0,0,0,117,8,0, 0,0,95,95,110,97,109,101,95,95,117,10,0,0,0,95, 95,109,111,100,117,108,101,95,95,117,12,0,0,0,95,95, - 113,117,97,108,110,97,109,101,95,95,117,7,0,0,0,95, - 95,100,111,99,95,95,117,8,0,0,0,95,95,105,110,105, - 116,95,95,117,11,0,0,0,95,99,104,101,99,107,95,110, - 97,109,101,117,12,0,0,0,103,101,116,95,102,105,108,101, - 110,97,109,101,117,8,0,0,0,103,101,116,95,100,97,116, - 97,40,1,0,0,0,117,10,0,0,0,95,95,108,111,99, + 113,117,97,108,110,97,109,101,95,95,117,10,0,0,0,112, + 97,116,104,95,109,116,105,109,101,117,10,0,0,0,112,97, + 116,104,95,115,116,97,116,115,117,8,0,0,0,115,101,116, + 95,100,97,116,97,117,10,0,0,0,103,101,116,95,115,111, + 117,114,99,101,117,8,0,0,0,103,101,116,95,99,111,100, + 101,117,11,0,0,0,108,111,97,100,95,109,111,100,117,108, + 101,40,1,0,0,0,117,10,0,0,0,95,95,108,111,99, 97,108,115,95,95,40,0,0,0,0,40,0,0,0,0,117, 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,11,0,0,0,95,70,105,108,101,76,111,97,100,101, - 114,52,2,0,0,115,8,0,0,0,16,3,6,2,12,6, - 18,5,117,11,0,0,0,95,70,105,108,101,76,111,97,100, - 101,114,99,1,0,0,0,0,0,0,0,1,0,0,0,2, - 0,0,0,66,0,0,0,115,50,0,0,0,124,0,0,69, - 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, - 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, - 0,100,5,0,132,0,0,90,5,0,100,6,0,83,40,7, - 0,0,0,117,17,0,0,0,95,83,111,117,114,99,101,70, - 105,108,101,76,111,97,100,101,114,117,62,0,0,0,67,111, - 110,99,114,101,116,101,32,105,109,112,108,101,109,101,110,116, - 97,116,105,111,110,32,111,102,32,83,111,117,114,99,101,76, - 111,97,100,101,114,32,117,115,105,110,103,32,116,104,101,32, - 102,105,108,101,32,115,121,115,116,101,109,46,99,2,0,0, - 0,0,0,0,0,3,0,0,0,3,0,0,0,67,0,0, - 0,115,39,0,0,0,116,0,0,106,1,0,124,1,0,131, - 1,0,125,2,0,105,2,0,124,2,0,106,2,0,100,1, - 0,54,124,2,0,106,3,0,100,2,0,54,83,40,3,0, - 0,0,117,32,0,0,0,82,101,116,117,114,110,32,116,104, - 101,32,109,101,116,97,100,97,116,32,102,111,114,32,116,104, - 101,32,112,97,116,104,46,117,5,0,0,0,109,116,105,109, - 101,117,4,0,0,0,115,105,122,101,40,4,0,0,0,117, - 3,0,0,0,95,111,115,117,4,0,0,0,115,116,97,116, - 117,8,0,0,0,115,116,95,109,116,105,109,101,117,7,0, - 0,0,115,116,95,115,105,122,101,40,3,0,0,0,117,4, - 0,0,0,115,101,108,102,117,4,0,0,0,112,97,116,104, - 117,2,0,0,0,115,116,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,10,0,0,0,112,97,116,104,95,115,116,97, - 116,115,78,2,0,0,115,4,0,0,0,0,2,15,1,117, - 28,0,0,0,95,83,111,117,114,99,101,70,105,108,101,76, - 111,97,100,101,114,46,112,97,116,104,95,115,116,97,116,115, - 99,3,0,0,0,0,0,0,0,8,0,0,0,13,0,0, - 0,67,0,0,0,115,254,0,0,0,124,1,0,106,0,0, - 116,1,0,131,1,0,92,3,0,125,3,0,125,4,0,125, - 5,0,103,0,0,125,6,0,120,60,0,124,3,0,114,92, - 0,116,2,0,124,3,0,131,1,0,12,114,92,0,124,3, - 0,106,0,0,116,1,0,131,1,0,92,3,0,125,3,0, - 125,4,0,125,7,0,124,6,0,106,3,0,124,7,0,131, - 1,0,1,113,33,0,87,120,97,0,116,4,0,124,6,0, - 131,1,0,68,93,83,0,125,7,0,116,5,0,124,3,0, - 124,7,0,131,2,0,125,3,0,121,17,0,116,6,0,106, - 7,0,124,3,0,131,1,0,1,87,113,106,0,4,116,8, - 0,107,10,0,114,167,0,1,1,1,119,106,0,89,113,106, - 0,4,116,9,0,107,10,0,114,188,0,1,1,1,100,1, - 0,83,89,113,106,0,88,113,106,0,87,121,30,0,116,10, - 0,124,1,0,124,2,0,131,2,0,1,116,11,0,100,2, - 0,124,1,0,131,2,0,1,87,110,24,0,4,116,9,0, - 116,8,0,102,2,0,107,10,0,114,249,0,1,1,1,89, - 110,1,0,88,100,1,0,83,40,3,0,0,0,117,27,0, - 0,0,87,114,105,116,101,32,98,121,116,101,115,32,100,97, - 116,97,32,116,111,32,97,32,102,105,108,101,46,78,117,12, - 0,0,0,99,114,101,97,116,101,100,32,123,33,114,125,40, - 12,0,0,0,117,10,0,0,0,114,112,97,114,116,105,116, - 105,111,110,117,8,0,0,0,112,97,116,104,95,115,101,112, - 117,11,0,0,0,95,112,97,116,104,95,105,115,100,105,114, - 117,6,0,0,0,97,112,112,101,110,100,117,8,0,0,0, - 114,101,118,101,114,115,101,100,117,10,0,0,0,95,112,97, - 116,104,95,106,111,105,110,117,3,0,0,0,95,111,115,117, - 5,0,0,0,109,107,100,105,114,117,15,0,0,0,70,105, - 108,101,69,120,105,115,116,115,69,114,114,111,114,117,15,0, - 0,0,80,101,114,109,105,115,115,105,111,110,69,114,114,111, - 114,117,13,0,0,0,95,119,114,105,116,101,95,97,116,111, - 109,105,99,117,15,0,0,0,118,101,114,98,111,115,101,95, - 109,101,115,115,97,103,101,40,8,0,0,0,117,4,0,0, - 0,115,101,108,102,117,4,0,0,0,112,97,116,104,117,4, - 0,0,0,100,97,116,97,117,6,0,0,0,112,97,114,101, - 110,116,117,1,0,0,0,95,117,8,0,0,0,102,105,108, - 101,110,97,109,101,117,10,0,0,0,112,97,116,104,95,112, - 97,114,116,115,117,4,0,0,0,112,97,114,116,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,8,0,0,0,115,101, - 116,95,100,97,116,97,83,2,0,0,115,36,0,0,0,0, - 2,24,1,6,2,22,1,24,1,17,2,19,1,15,1,3, - 1,17,1,13,2,7,1,13,3,13,1,3,1,13,1,17, - 1,19,3,117,26,0,0,0,95,83,111,117,114,99,101,70, - 105,108,101,76,111,97,100,101,114,46,115,101,116,95,100,97, - 116,97,78,40,6,0,0,0,117,8,0,0,0,95,95,110, - 97,109,101,95,95,117,10,0,0,0,95,95,109,111,100,117, - 108,101,95,95,117,12,0,0,0,95,95,113,117,97,108,110, - 97,109,101,95,95,117,7,0,0,0,95,95,100,111,99,95, - 95,117,10,0,0,0,112,97,116,104,95,115,116,97,116,115, - 117,8,0,0,0,115,101,116,95,100,97,116,97,40,1,0, - 0,0,117,10,0,0,0,95,95,108,111,99,97,108,115,95, - 95,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,17,0, - 0,0,95,83,111,117,114,99,101,70,105,108,101,76,111,97, - 100,101,114,74,2,0,0,115,6,0,0,0,16,2,6,2, - 12,5,117,17,0,0,0,95,83,111,117,114,99,101,70,105, - 108,101,76,111,97,100,101,114,99,1,0,0,0,0,0,0, - 0,1,0,0,0,2,0,0,0,66,0,0,0,115,62,0, + 62,117,12,0,0,0,83,111,117,114,99,101,76,111,97,100, + 101,114,204,1,0,0,115,12,0,0,0,16,2,12,6,12, + 12,12,9,12,13,12,61,117,12,0,0,0,83,111,117,114, + 99,101,76,111,97,100,101,114,99,1,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,66,0,0,0,115,68,0, 0,0,124,0,0,69,101,0,0,90,1,0,100,0,0,90, 2,0,100,1,0,90,3,0,100,2,0,100,3,0,132,0, - 0,90,4,0,100,4,0,100,5,0,132,0,0,90,5,0, - 100,6,0,100,7,0,132,0,0,90,6,0,100,8,0,83, - 40,9,0,0,0,117,21,0,0,0,95,83,111,117,114,99, - 101,108,101,115,115,70,105,108,101,76,111,97,100,101,114,117, - 45,0,0,0,76,111,97,100,101,114,32,119,104,105,99,104, - 32,104,97,110,100,108,101,115,32,115,111,117,114,99,101,108, - 101,115,115,32,102,105,108,101,32,105,109,112,111,114,116,115, - 46,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,67,0,0,0,115,19,0,0,0,124,0,0,106,0, - 0,124,1,0,100,1,0,100,2,0,131,1,1,83,40,3, - 0,0,0,78,117,10,0,0,0,115,111,117,114,99,101,108, - 101,115,115,84,40,2,0,0,0,117,12,0,0,0,95,108, - 111,97,100,95,109,111,100,117,108,101,117,4,0,0,0,84, - 114,117,101,40,2,0,0,0,117,4,0,0,0,115,101,108, - 102,117,8,0,0,0,102,117,108,108,110,97,109,101,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,11,0,0,0,108, - 111,97,100,95,109,111,100,117,108,101,116,2,0,0,115,2, - 0,0,0,0,1,117,33,0,0,0,95,83,111,117,114,99, - 101,108,101,115,115,70,105,108,101,76,111,97,100,101,114,46, - 108,111,97,100,95,109,111,100,117,108,101,99,2,0,0,0, - 0,0,0,0,6,0,0,0,6,0,0,0,67,0,0,0, - 115,138,0,0,0,124,0,0,106,0,0,124,1,0,131,1, - 0,125,2,0,124,0,0,106,1,0,124,2,0,131,1,0, - 125,3,0,124,0,0,106,2,0,124,1,0,124,3,0,124, - 2,0,100,0,0,131,4,0,125,4,0,116,4,0,106,5, - 0,124,4,0,131,1,0,125,5,0,116,6,0,124,5,0, - 116,7,0,131,2,0,114,101,0,116,8,0,100,1,0,124, - 2,0,131,2,0,1,124,5,0,83,116,9,0,100,2,0, - 106,10,0,124,2,0,131,1,0,100,3,0,124,1,0,100, - 4,0,124,2,0,131,1,2,130,1,0,100,0,0,83,40, - 5,0,0,0,78,117,21,0,0,0,99,111,100,101,32,111, - 98,106,101,99,116,32,102,114,111,109,32,123,33,114,125,117, - 21,0,0,0,78,111,110,45,99,111,100,101,32,111,98,106, - 101,99,116,32,105,110,32,123,125,117,4,0,0,0,110,97, - 109,101,117,4,0,0,0,112,97,116,104,40,11,0,0,0, - 117,12,0,0,0,103,101,116,95,102,105,108,101,110,97,109, - 101,117,8,0,0,0,103,101,116,95,100,97,116,97,117,20, - 0,0,0,95,98,121,116,101,115,95,102,114,111,109,95,98, - 121,116,101,99,111,100,101,117,4,0,0,0,78,111,110,101, - 117,7,0,0,0,109,97,114,115,104,97,108,117,5,0,0, - 0,108,111,97,100,115,117,10,0,0,0,105,115,105,110,115, - 116,97,110,99,101,117,9,0,0,0,99,111,100,101,95,116, - 121,112,101,117,15,0,0,0,118,101,114,98,111,115,101,95, - 109,101,115,115,97,103,101,117,11,0,0,0,73,109,112,111, - 114,116,69,114,114,111,114,117,6,0,0,0,102,111,114,109, - 97,116,40,6,0,0,0,117,4,0,0,0,115,101,108,102, - 117,8,0,0,0,102,117,108,108,110,97,109,101,117,4,0, - 0,0,112,97,116,104,117,4,0,0,0,100,97,116,97,117, - 10,0,0,0,98,121,116,101,115,95,100,97,116,97,117,5, - 0,0,0,102,111,117,110,100,40,0,0,0,0,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,8,0,0,0,103,101,116,95,99,111,100, - 101,119,2,0,0,115,18,0,0,0,0,1,15,1,15,1, - 24,1,15,1,15,1,13,1,4,2,18,1,117,30,0,0, - 0,95,83,111,117,114,99,101,108,101,115,115,70,105,108,101, - 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,4,0,0,0,100,1,0,83,40,2,0, - 0,0,117,39,0,0,0,82,101,116,117,114,110,32,78,111, - 110,101,32,97,115,32,116,104,101,114,101,32,105,115,32,110, - 111,32,115,111,117,114,99,101,32,99,111,100,101,46,78,40, - 1,0,0,0,117,4,0,0,0,78,111,110,101,40,2,0, + 0,90,4,0,101,5,0,100,4,0,100,5,0,132,0,0, + 131,1,0,90,6,0,100,6,0,100,7,0,132,0,0,90, + 7,0,100,8,0,83,40,9,0,0,0,117,11,0,0,0, + 95,70,105,108,101,76,111,97,100,101,114,117,103,0,0,0, + 66,97,115,101,32,102,105,108,101,32,108,111,97,100,101,114, + 32,99,108,97,115,115,32,119,104,105,99,104,32,105,109,112, + 108,101,109,101,110,116,115,32,116,104,101,32,108,111,97,100, + 101,114,32,112,114,111,116,111,99,111,108,32,109,101,116,104, + 111,100,115,32,116,104,97,116,10,32,32,32,32,114,101,113, + 117,105,114,101,32,102,105,108,101,32,115,121,115,116,101,109, + 32,117,115,97,103,101,46,99,3,0,0,0,0,0,0,0, + 3,0,0,0,2,0,0,0,67,0,0,0,115,22,0,0, + 0,124,1,0,124,0,0,95,0,0,124,2,0,124,0,0, + 95,1,0,100,1,0,83,40,2,0,0,0,117,75,0,0, + 0,67,97,99,104,101,32,116,104,101,32,109,111,100,117,108, + 101,32,110,97,109,101,32,97,110,100,32,116,104,101,32,112, + 97,116,104,32,116,111,32,116,104,101,32,102,105,108,101,32, + 102,111,117,110,100,32,98,121,32,116,104,101,10,32,32,32, + 32,32,32,32,32,102,105,110,100,101,114,46,78,40,2,0, + 0,0,117,5,0,0,0,95,110,97,109,101,117,5,0,0, + 0,95,112,97,116,104,40,3,0,0,0,117,4,0,0,0, + 115,101,108,102,117,8,0,0,0,102,117,108,108,110,97,109, + 101,117,4,0,0,0,112,97,116,104,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,8,0,0,0,95,95,105,110,105, + 116,95,95,67,2,0,0,115,4,0,0,0,0,3,9,1, + 117,20,0,0,0,95,70,105,108,101,76,111,97,100,101,114, + 46,95,95,105,110,105,116,95,95,99,2,0,0,0,0,0, + 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,7, + 0,0,0,124,0,0,106,0,0,83,40,1,0,0,0,117, + 58,0,0,0,82,101,116,117,114,110,32,116,104,101,32,112, + 97,116,104,32,116,111,32,116,104,101,32,115,111,117,114,99, + 101,32,102,105,108,101,32,97,115,32,102,111,117,110,100,32, + 98,121,32,116,104,101,32,102,105,110,100,101,114,46,40,1, + 0,0,0,117,5,0,0,0,95,112,97,116,104,40,2,0, 0,0,117,4,0,0,0,115,101,108,102,117,8,0,0,0, 102,117,108,108,110,97,109,101,40,0,0,0,0,40,0,0, 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,10,0,0,0,103,101,116,95,115,111,117, - 114,99,101,131,2,0,0,115,2,0,0,0,0,2,117,32, - 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, - 108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, - 114,99,101,78,40,7,0,0,0,117,8,0,0,0,95,95, + 114,97,112,62,117,12,0,0,0,103,101,116,95,102,105,108, + 101,110,97,109,101,73,2,0,0,115,2,0,0,0,0,3, + 117,24,0,0,0,95,70,105,108,101,76,111,97,100,101,114, + 46,103,101,116,95,102,105,108,101,110,97,109,101,99,2,0, + 0,0,0,0,0,0,3,0,0,0,8,0,0,0,67,0, + 0,0,115,41,0,0,0,116,0,0,106,1,0,124,1,0, + 100,1,0,131,2,0,143,17,0,125,2,0,124,2,0,106, + 2,0,131,0,0,83,87,100,2,0,81,88,100,2,0,83, + 40,3,0,0,0,117,39,0,0,0,82,101,116,117,114,110, + 32,116,104,101,32,100,97,116,97,32,102,114,111,109,32,112, + 97,116,104,32,97,115,32,114,97,119,32,98,121,116,101,115, + 46,117,1,0,0,0,114,78,40,3,0,0,0,117,3,0, + 0,0,95,105,111,117,6,0,0,0,70,105,108,101,73,79, + 117,4,0,0,0,114,101,97,100,40,3,0,0,0,117,4, + 0,0,0,115,101,108,102,117,4,0,0,0,112,97,116,104, + 117,4,0,0,0,102,105,108,101,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,8,0,0,0,103,101,116,95,100,97, + 116,97,78,2,0,0,115,4,0,0,0,0,2,21,1,117, + 20,0,0,0,95,70,105,108,101,76,111,97,100,101,114,46, + 103,101,116,95,100,97,116,97,78,40,8,0,0,0,117,8, + 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, + 95,95,109,111,100,117,108,101,95,95,117,12,0,0,0,95, + 95,113,117,97,108,110,97,109,101,95,95,117,7,0,0,0, + 95,95,100,111,99,95,95,117,8,0,0,0,95,95,105,110, + 105,116,95,95,117,11,0,0,0,95,99,104,101,99,107,95, + 110,97,109,101,117,12,0,0,0,103,101,116,95,102,105,108, + 101,110,97,109,101,117,8,0,0,0,103,101,116,95,100,97, + 116,97,40,1,0,0,0,117,10,0,0,0,95,95,108,111, + 99,97,108,115,95,95,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,11,0,0,0,95,70,105,108,101,76,111,97,100, + 101,114,62,2,0,0,115,8,0,0,0,16,3,6,2,12, + 6,18,5,117,11,0,0,0,95,70,105,108,101,76,111,97, + 100,101,114,99,1,0,0,0,0,0,0,0,1,0,0,0, + 2,0,0,0,66,0,0,0,115,50,0,0,0,124,0,0, + 69,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, + 90,3,0,100,2,0,100,3,0,132,0,0,90,4,0,100, + 4,0,100,5,0,132,0,0,90,5,0,100,6,0,83,40, + 7,0,0,0,117,17,0,0,0,95,83,111,117,114,99,101, + 70,105,108,101,76,111,97,100,101,114,117,62,0,0,0,67, + 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,111,102,32,83,111,117,114,99,101, + 76,111,97,100,101,114,32,117,115,105,110,103,32,116,104,101, + 32,102,105,108,101,32,115,121,115,116,101,109,46,99,2,0, + 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, + 0,0,115,39,0,0,0,116,0,0,106,1,0,124,1,0, + 131,1,0,125,2,0,105,2,0,124,2,0,106,2,0,100, + 1,0,54,124,2,0,106,3,0,100,2,0,54,83,40,3, + 0,0,0,117,32,0,0,0,82,101,116,117,114,110,32,116, + 104,101,32,109,101,116,97,100,97,116,32,102,111,114,32,116, + 104,101,32,112,97,116,104,46,117,5,0,0,0,109,116,105, + 109,101,117,4,0,0,0,115,105,122,101,40,4,0,0,0, + 117,3,0,0,0,95,111,115,117,4,0,0,0,115,116,97, + 116,117,8,0,0,0,115,116,95,109,116,105,109,101,117,7, + 0,0,0,115,116,95,115,105,122,101,40,3,0,0,0,117, + 4,0,0,0,115,101,108,102,117,4,0,0,0,112,97,116, + 104,117,2,0,0,0,115,116,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,10,0,0,0,112,97,116,104,95,115,116, + 97,116,115,88,2,0,0,115,4,0,0,0,0,2,15,1, + 117,28,0,0,0,95,83,111,117,114,99,101,70,105,108,101, + 76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,116, + 115,99,3,0,0,0,0,0,0,0,8,0,0,0,13,0, + 0,0,67,0,0,0,115,254,0,0,0,124,1,0,106,0, + 0,116,1,0,131,1,0,92,3,0,125,3,0,125,4,0, + 125,5,0,103,0,0,125,6,0,120,60,0,124,3,0,114, + 92,0,116,2,0,124,3,0,131,1,0,12,114,92,0,124, + 3,0,106,0,0,116,1,0,131,1,0,92,3,0,125,3, + 0,125,4,0,125,7,0,124,6,0,106,3,0,124,7,0, + 131,1,0,1,113,33,0,87,120,97,0,116,4,0,124,6, + 0,131,1,0,68,93,83,0,125,7,0,116,5,0,124,3, + 0,124,7,0,131,2,0,125,3,0,121,17,0,116,6,0, + 106,7,0,124,3,0,131,1,0,1,87,113,106,0,4,116, + 8,0,107,10,0,114,167,0,1,1,1,119,106,0,89,113, + 106,0,4,116,9,0,107,10,0,114,188,0,1,1,1,100, + 1,0,83,89,113,106,0,88,113,106,0,87,121,30,0,116, + 10,0,124,1,0,124,2,0,131,2,0,1,116,11,0,100, + 2,0,124,1,0,131,2,0,1,87,110,24,0,4,116,9, + 0,116,8,0,102,2,0,107,10,0,114,249,0,1,1,1, + 89,110,1,0,88,100,1,0,83,40,3,0,0,0,117,27, + 0,0,0,87,114,105,116,101,32,98,121,116,101,115,32,100, + 97,116,97,32,116,111,32,97,32,102,105,108,101,46,78,117, + 12,0,0,0,99,114,101,97,116,101,100,32,123,33,114,125, + 40,12,0,0,0,117,10,0,0,0,114,112,97,114,116,105, + 116,105,111,110,117,8,0,0,0,112,97,116,104,95,115,101, + 112,117,11,0,0,0,95,112,97,116,104,95,105,115,100,105, + 114,117,6,0,0,0,97,112,112,101,110,100,117,8,0,0, + 0,114,101,118,101,114,115,101,100,117,10,0,0,0,95,112, + 97,116,104,95,106,111,105,110,117,3,0,0,0,95,111,115, + 117,5,0,0,0,109,107,100,105,114,117,15,0,0,0,70, + 105,108,101,69,120,105,115,116,115,69,114,114,111,114,117,15, + 0,0,0,80,101,114,109,105,115,115,105,111,110,69,114,114, + 111,114,117,13,0,0,0,95,119,114,105,116,101,95,97,116, + 111,109,105,99,117,15,0,0,0,118,101,114,98,111,115,101, + 95,109,101,115,115,97,103,101,40,8,0,0,0,117,4,0, + 0,0,115,101,108,102,117,4,0,0,0,112,97,116,104,117, + 4,0,0,0,100,97,116,97,117,6,0,0,0,112,97,114, + 101,110,116,117,1,0,0,0,95,117,8,0,0,0,102,105, + 108,101,110,97,109,101,117,10,0,0,0,112,97,116,104,95, + 112,97,114,116,115,117,4,0,0,0,112,97,114,116,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,8,0,0,0,115, + 101,116,95,100,97,116,97,93,2,0,0,115,36,0,0,0, + 0,2,24,1,6,2,22,1,24,1,17,2,19,1,15,1, + 3,1,17,1,13,2,7,1,13,3,13,1,3,1,13,1, + 17,1,19,3,117,26,0,0,0,95,83,111,117,114,99,101, + 70,105,108,101,76,111,97,100,101,114,46,115,101,116,95,100, + 97,116,97,78,40,6,0,0,0,117,8,0,0,0,95,95, 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, - 95,95,117,11,0,0,0,108,111,97,100,95,109,111,100,117, - 108,101,117,8,0,0,0,103,101,116,95,99,111,100,101,117, - 10,0,0,0,103,101,116,95,115,111,117,114,99,101,40,1, + 95,95,117,10,0,0,0,112,97,116,104,95,115,116,97,116, + 115,117,8,0,0,0,115,101,116,95,100,97,116,97,40,1, 0,0,0,117,10,0,0,0,95,95,108,111,99,97,108,115, 95,95,40,0,0,0,0,40,0,0,0,0,117,29,0,0, 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,21, - 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, - 108,101,76,111,97,100,101,114,112,2,0,0,115,8,0,0, - 0,16,2,6,2,12,3,12,12,117,21,0,0,0,95,83, - 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, - 100,101,114,99,1,0,0,0,0,0,0,0,1,0,0,0, - 5,0,0,0,66,0,0,0,115,122,0,0,0,124,0,0, - 69,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, - 90,3,0,100,2,0,100,3,0,132,0,0,90,4,0,101, - 5,0,101,6,0,101,7,0,100,4,0,100,5,0,132,0, - 0,131,1,0,131,1,0,131,1,0,90,8,0,101,5,0, - 100,6,0,100,7,0,132,0,0,131,1,0,90,9,0,101, - 5,0,100,8,0,100,9,0,132,0,0,131,1,0,90,10, - 0,101,5,0,100,10,0,100,11,0,132,0,0,131,1,0, - 90,11,0,100,12,0,83,40,13,0,0,0,117,20,0,0, - 0,95,69,120,116,101,110,115,105,111,110,70,105,108,101,76, - 111,97,100,101,114,117,93,0,0,0,76,111,97,100,101,114, - 32,102,111,114,32,101,120,116,101,110,115,105,111,110,32,109, - 111,100,117,108,101,115,46,10,10,32,32,32,32,84,104,101, - 32,99,111,110,115,116,114,117,99,116,111,114,32,105,115,32, - 100,101,115,105,103,110,101,100,32,116,111,32,119,111,114,107, - 32,119,105,116,104,32,70,105,108,101,70,105,110,100,101,114, - 46,10,10,32,32,32,32,99,3,0,0,0,0,0,0,0, - 3,0,0,0,2,0,0,0,67,0,0,0,115,22,0,0, - 0,124,1,0,124,0,0,95,0,0,124,2,0,124,0,0, - 95,1,0,100,0,0,83,40,1,0,0,0,78,40,2,0, - 0,0,117,5,0,0,0,95,110,97,109,101,117,5,0,0, - 0,95,112,97,116,104,40,3,0,0,0,117,4,0,0,0, - 115,101,108,102,117,4,0,0,0,110,97,109,101,117,4,0, - 0,0,112,97,116,104,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,8,0,0,0,95,95,105,110,105,116,95,95,144, - 2,0,0,115,4,0,0,0,0,1,9,1,117,29,0,0, - 0,95,69,120,116,101,110,115,105,111,110,70,105,108,101,76, - 111,97,100,101,114,46,95,95,105,110,105,116,95,95,99,2, - 0,0,0,0,0,0,0,4,0,0,0,9,0,0,0,67, - 0,0,0,115,113,0,0,0,124,1,0,116,0,0,106,1, - 0,107,6,0,125,2,0,121,45,0,116,2,0,106,3,0, - 124,1,0,124,0,0,106,4,0,131,2,0,125,3,0,116, - 5,0,100,1,0,124,0,0,106,4,0,131,2,0,1,124, - 3,0,83,87,110,46,0,1,1,1,124,2,0,12,114,101, - 0,124,1,0,116,0,0,106,1,0,107,6,0,114,101,0, - 116,0,0,106,1,0,124,1,0,61,110,0,0,130,0,0, - 89,110,1,0,88,100,2,0,83,40,3,0,0,0,117,25, - 0,0,0,76,111,97,100,32,97,110,32,101,120,116,101,110, - 115,105,111,110,32,109,111,100,117,108,101,46,117,33,0,0, - 0,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, - 101,32,108,111,97,100,101,100,32,102,114,111,109,32,123,33, - 114,125,78,40,6,0,0,0,117,3,0,0,0,115,121,115, - 117,7,0,0,0,109,111,100,117,108,101,115,117,3,0,0, - 0,105,109,112,117,12,0,0,0,108,111,97,100,95,100,121, - 110,97,109,105,99,117,5,0,0,0,95,112,97,116,104,117, - 15,0,0,0,118,101,114,98,111,115,101,95,109,101,115,115, - 97,103,101,40,4,0,0,0,117,4,0,0,0,115,101,108, - 102,117,8,0,0,0,102,117,108,108,110,97,109,101,117,9, - 0,0,0,105,115,95,114,101,108,111,97,100,117,6,0,0, - 0,109,111,100,117,108,101,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,11,0,0,0,108,111,97,100,95,109,111,100, - 117,108,101,148,2,0,0,115,18,0,0,0,0,5,15,1, - 3,1,21,1,16,1,8,1,3,1,22,1,13,1,117,32, - 0,0,0,95,69,120,116,101,110,115,105,111,110,70,105,108, - 101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, - 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,0, - 83,40,2,0,0,0,117,59,0,0,0,82,101,116,117,114, - 110,32,70,97,108,115,101,32,97,115,32,97,110,32,101,120, - 116,101,110,115,105,111,110,32,109,111,100,117,108,101,32,99, - 97,110,32,110,101,118,101,114,32,98,101,32,97,32,112,97, - 99,107,97,103,101,46,70,40,1,0,0,0,117,5,0,0, - 0,70,97,108,115,101,40,2,0,0,0,117,4,0,0,0, - 115,101,108,102,117,8,0,0,0,102,117,108,108,110,97,109, - 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,10,0, - 0,0,105,115,95,112,97,99,107,97,103,101,163,2,0,0, - 115,2,0,0,0,0,3,117,31,0,0,0,95,69,120,116, - 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, - 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, - 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, - 115,4,0,0,0,100,1,0,83,40,2,0,0,0,117,63, - 0,0,0,82,101,116,117,114,110,32,78,111,110,101,32,97, - 115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,109, - 111,100,117,108,101,32,99,97,110,110,111,116,32,99,114,101, - 97,116,101,32,97,32,99,111,100,101,32,111,98,106,101,99, - 116,46,78,40,1,0,0,0,117,4,0,0,0,78,111,110, - 101,40,2,0,0,0,117,4,0,0,0,115,101,108,102,117, - 8,0,0,0,102,117,108,108,110,97,109,101,40,0,0,0, - 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, - 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, - 111,116,115,116,114,97,112,62,117,8,0,0,0,103,101,116, - 95,99,111,100,101,168,2,0,0,115,2,0,0,0,0,3, - 117,29,0,0,0,95,69,120,116,101,110,115,105,111,110,70, - 105,108,101,76,111,97,100,101,114,46,103,101,116,95,99,111, - 100,101,99,2,0,0,0,0,0,0,0,2,0,0,0,1, - 0,0,0,67,0,0,0,115,4,0,0,0,100,1,0,83, - 40,2,0,0,0,117,53,0,0,0,82,101,116,117,114,110, - 32,78,111,110,101,32,97,115,32,101,120,116,101,110,115,105, - 111,110,32,109,111,100,117,108,101,115,32,104,97,118,101,32, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,17, + 0,0,0,95,83,111,117,114,99,101,70,105,108,101,76,111, + 97,100,101,114,84,2,0,0,115,6,0,0,0,16,2,6, + 2,12,5,117,17,0,0,0,95,83,111,117,114,99,101,70, + 105,108,101,76,111,97,100,101,114,99,1,0,0,0,0,0, + 0,0,1,0,0,0,2,0,0,0,66,0,0,0,115,62, + 0,0,0,124,0,0,69,101,0,0,90,1,0,100,0,0, + 90,2,0,100,1,0,90,3,0,100,2,0,100,3,0,132, + 0,0,90,4,0,100,4,0,100,5,0,132,0,0,90,5, + 0,100,6,0,100,7,0,132,0,0,90,6,0,100,8,0, + 83,40,9,0,0,0,117,21,0,0,0,95,83,111,117,114, + 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, + 117,45,0,0,0,76,111,97,100,101,114,32,119,104,105,99, + 104,32,104,97,110,100,108,101,115,32,115,111,117,114,99,101, + 108,101,115,115,32,102,105,108,101,32,105,109,112,111,114,116, + 115,46,99,2,0,0,0,0,0,0,0,2,0,0,0,4, + 0,0,0,67,0,0,0,115,19,0,0,0,124,0,0,106, + 0,0,124,1,0,100,1,0,100,2,0,131,1,1,83,40, + 3,0,0,0,78,117,10,0,0,0,115,111,117,114,99,101, + 108,101,115,115,84,40,2,0,0,0,117,12,0,0,0,95, + 108,111,97,100,95,109,111,100,117,108,101,117,4,0,0,0, + 84,114,117,101,40,2,0,0,0,117,4,0,0,0,115,101, + 108,102,117,8,0,0,0,102,117,108,108,110,97,109,101,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, + 108,111,97,100,95,109,111,100,117,108,101,126,2,0,0,115, + 2,0,0,0,0,1,117,33,0,0,0,95,83,111,117,114, + 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, + 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,6,0,0,0,6,0,0,0,67,0,0, + 0,115,138,0,0,0,124,0,0,106,0,0,124,1,0,131, + 1,0,125,2,0,124,0,0,106,1,0,124,2,0,131,1, + 0,125,3,0,124,0,0,106,2,0,124,1,0,124,3,0, + 124,2,0,100,0,0,131,4,0,125,4,0,116,4,0,106, + 5,0,124,4,0,131,1,0,125,5,0,116,6,0,124,5, + 0,116,7,0,131,2,0,114,101,0,116,8,0,100,1,0, + 124,2,0,131,2,0,1,124,5,0,83,116,9,0,100,2, + 0,106,10,0,124,2,0,131,1,0,100,3,0,124,1,0, + 100,4,0,124,2,0,131,1,2,130,1,0,100,0,0,83, + 40,5,0,0,0,78,117,21,0,0,0,99,111,100,101,32, + 111,98,106,101,99,116,32,102,114,111,109,32,123,33,114,125, + 117,21,0,0,0,78,111,110,45,99,111,100,101,32,111,98, + 106,101,99,116,32,105,110,32,123,125,117,4,0,0,0,110, + 97,109,101,117,4,0,0,0,112,97,116,104,40,11,0,0, + 0,117,12,0,0,0,103,101,116,95,102,105,108,101,110,97, + 109,101,117,8,0,0,0,103,101,116,95,100,97,116,97,117, + 20,0,0,0,95,98,121,116,101,115,95,102,114,111,109,95, + 98,121,116,101,99,111,100,101,117,4,0,0,0,78,111,110, + 101,117,7,0,0,0,109,97,114,115,104,97,108,117,5,0, + 0,0,108,111,97,100,115,117,10,0,0,0,105,115,105,110, + 115,116,97,110,99,101,117,9,0,0,0,99,111,100,101,95, + 116,121,112,101,117,15,0,0,0,118,101,114,98,111,115,101, + 95,109,101,115,115,97,103,101,117,11,0,0,0,73,109,112, + 111,114,116,69,114,114,111,114,117,6,0,0,0,102,111,114, + 109,97,116,40,6,0,0,0,117,4,0,0,0,115,101,108, + 102,117,8,0,0,0,102,117,108,108,110,97,109,101,117,4, + 0,0,0,112,97,116,104,117,4,0,0,0,100,97,116,97, + 117,10,0,0,0,98,121,116,101,115,95,100,97,116,97,117, + 5,0,0,0,102,111,117,110,100,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,8,0,0,0,103,101,116,95,99,111, + 100,101,129,2,0,0,115,18,0,0,0,0,1,15,1,15, + 1,24,1,15,1,15,1,13,1,4,2,18,1,117,30,0, + 0,0,95,83,111,117,114,99,101,108,101,115,115,70,105,108, + 101,76,111,97,100,101,114,46,103,101,116,95,99,111,100,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,115,4,0,0,0,100,1,0,83,40,2, + 0,0,0,117,39,0,0,0,82,101,116,117,114,110,32,78, + 111,110,101,32,97,115,32,116,104,101,114,101,32,105,115,32, 110,111,32,115,111,117,114,99,101,32,99,111,100,101,46,78, 40,1,0,0,0,117,4,0,0,0,78,111,110,101,40,2, 0,0,0,117,4,0,0,0,115,101,108,102,117,8,0,0, @@ -1832,1261 +1726,1384 @@ 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, 116,114,97,112,62,117,10,0,0,0,103,101,116,95,115,111, - 117,114,99,101,173,2,0,0,115,2,0,0,0,0,3,117, - 31,0,0,0,95,69,120,116,101,110,115,105,111,110,70,105, - 108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, - 114,99,101,78,40,12,0,0,0,117,8,0,0,0,95,95, - 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, - 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, - 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, - 95,95,117,8,0,0,0,95,95,105,110,105,116,95,95,117, - 11,0,0,0,95,99,104,101,99,107,95,110,97,109,101,117, - 11,0,0,0,115,101,116,95,112,97,99,107,97,103,101,117, - 10,0,0,0,115,101,116,95,108,111,97,100,101,114,117,11, - 0,0,0,108,111,97,100,95,109,111,100,117,108,101,117,10, - 0,0,0,105,115,95,112,97,99,107,97,103,101,117,8,0, - 0,0,103,101,116,95,99,111,100,101,117,10,0,0,0,103, - 101,116,95,115,111,117,114,99,101,40,1,0,0,0,117,10, - 0,0,0,95,95,108,111,99,97,108,115,95,95,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,20,0,0,0,95,69, + 117,114,99,101,141,2,0,0,115,2,0,0,0,0,2,117, + 32,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, + 105,108,101,76,111,97,100,101,114,46,103,101,116,95,115,111, + 117,114,99,101,78,40,7,0,0,0,117,8,0,0,0,95, + 95,110,97,109,101,95,95,117,10,0,0,0,95,95,109,111, + 100,117,108,101,95,95,117,12,0,0,0,95,95,113,117,97, + 108,110,97,109,101,95,95,117,7,0,0,0,95,95,100,111, + 99,95,95,117,11,0,0,0,108,111,97,100,95,109,111,100, + 117,108,101,117,8,0,0,0,103,101,116,95,99,111,100,101, + 117,10,0,0,0,103,101,116,95,115,111,117,114,99,101,40, + 1,0,0,0,117,10,0,0,0,95,95,108,111,99,97,108, + 115,95,95,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, + 105,108,101,76,111,97,100,101,114,122,2,0,0,115,8,0, + 0,0,16,2,6,2,12,3,12,12,117,21,0,0,0,95, + 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, + 97,100,101,114,99,1,0,0,0,0,0,0,0,1,0,0, + 0,5,0,0,0,66,0,0,0,115,122,0,0,0,124,0, + 0,69,101,0,0,90,1,0,100,0,0,90,2,0,100,1, + 0,90,3,0,100,2,0,100,3,0,132,0,0,90,4,0, + 101,5,0,101,6,0,101,7,0,100,4,0,100,5,0,132, + 0,0,131,1,0,131,1,0,131,1,0,90,8,0,101,5, + 0,100,6,0,100,7,0,132,0,0,131,1,0,90,9,0, + 101,5,0,100,8,0,100,9,0,132,0,0,131,1,0,90, + 10,0,101,5,0,100,10,0,100,11,0,132,0,0,131,1, + 0,90,11,0,100,12,0,83,40,13,0,0,0,117,20,0, + 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,117,93,0,0,0,76,111,97,100,101, + 114,32,102,111,114,32,101,120,116,101,110,115,105,111,110,32, + 109,111,100,117,108,101,115,46,10,10,32,32,32,32,84,104, + 101,32,99,111,110,115,116,114,117,99,116,111,114,32,105,115, + 32,100,101,115,105,103,110,101,100,32,116,111,32,119,111,114, + 107,32,119,105,116,104,32,70,105,108,101,70,105,110,100,101, + 114,46,10,10,32,32,32,32,99,3,0,0,0,0,0,0, + 0,3,0,0,0,2,0,0,0,67,0,0,0,115,22,0, + 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, + 0,95,1,0,100,0,0,83,40,1,0,0,0,78,40,2, + 0,0,0,117,5,0,0,0,95,110,97,109,101,117,5,0, + 0,0,95,112,97,116,104,40,3,0,0,0,117,4,0,0, + 0,115,101,108,102,117,4,0,0,0,110,97,109,101,117,4, + 0,0,0,112,97,116,104,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,8,0,0,0,95,95,105,110,105,116,95,95, + 154,2,0,0,115,4,0,0,0,0,1,9,1,117,29,0, + 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,46,95,95,105,110,105,116,95,95,99, + 2,0,0,0,0,0,0,0,4,0,0,0,9,0,0,0, + 67,0,0,0,115,113,0,0,0,124,1,0,116,0,0,106, + 1,0,107,6,0,125,2,0,121,45,0,116,2,0,106,3, + 0,124,1,0,124,0,0,106,4,0,131,2,0,125,3,0, + 116,5,0,100,1,0,124,0,0,106,4,0,131,2,0,1, + 124,3,0,83,87,110,46,0,1,1,1,124,2,0,12,114, + 101,0,124,1,0,116,0,0,106,1,0,107,6,0,114,101, + 0,116,0,0,106,1,0,124,1,0,61,110,0,0,130,0, + 0,89,110,1,0,88,100,2,0,83,40,3,0,0,0,117, + 25,0,0,0,76,111,97,100,32,97,110,32,101,120,116,101, + 110,115,105,111,110,32,109,111,100,117,108,101,46,117,33,0, + 0,0,101,120,116,101,110,115,105,111,110,32,109,111,100,117, + 108,101,32,108,111,97,100,101,100,32,102,114,111,109,32,123, + 33,114,125,78,40,6,0,0,0,117,3,0,0,0,115,121, + 115,117,7,0,0,0,109,111,100,117,108,101,115,117,4,0, + 0,0,95,105,109,112,117,12,0,0,0,108,111,97,100,95, + 100,121,110,97,109,105,99,117,5,0,0,0,95,112,97,116, + 104,117,15,0,0,0,118,101,114,98,111,115,101,95,109,101, + 115,115,97,103,101,40,4,0,0,0,117,4,0,0,0,115, + 101,108,102,117,8,0,0,0,102,117,108,108,110,97,109,101, + 117,9,0,0,0,105,115,95,114,101,108,111,97,100,117,6, + 0,0,0,109,111,100,117,108,101,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,11,0,0,0,108,111,97,100,95,109, + 111,100,117,108,101,158,2,0,0,115,18,0,0,0,0,5, + 15,1,3,1,21,1,16,1,8,1,3,1,22,1,13,1, + 117,32,0,0,0,95,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,46,108,111,97,100,95,109, + 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, + 1,0,83,40,2,0,0,0,117,59,0,0,0,82,101,116, + 117,114,110,32,70,97,108,115,101,32,97,115,32,97,110,32, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, + 32,99,97,110,32,110,101,118,101,114,32,98,101,32,97,32, + 112,97,99,107,97,103,101,46,70,40,1,0,0,0,117,5, + 0,0,0,70,97,108,115,101,40,2,0,0,0,117,4,0, + 0,0,115,101,108,102,117,8,0,0,0,102,117,108,108,110, + 97,109,101,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 10,0,0,0,105,115,95,112,97,99,107,97,103,101,173,2, + 0,0,115,2,0,0,0,0,3,117,31,0,0,0,95,69, 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,136,2,0,0,115,16,0,0,0,16,6,6,2,12, - 4,3,1,3,1,24,13,18,5,18,5,117,20,0,0,0, - 95,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,99,1,0,0,0,0,0,0,0,1,0,0, - 0,4,0,0,0,66,0,0,0,115,89,0,0,0,124,0, - 0,69,101,0,0,90,1,0,100,0,0,90,2,0,100,1, - 0,90,3,0,101,4,0,100,8,0,100,2,0,100,3,0, - 132,1,0,131,1,0,90,6,0,101,4,0,100,8,0,100, - 4,0,100,5,0,132,1,0,131,1,0,90,7,0,101,4, - 0,100,8,0,100,6,0,100,7,0,132,1,0,131,1,0, - 90,8,0,100,8,0,83,40,9,0,0,0,117,10,0,0, - 0,80,97,116,104,70,105,110,100,101,114,117,63,0,0,0, - 77,101,116,97,32,112,97,116,104,32,102,105,110,100,101,114, - 32,102,111,114,32,115,121,115,46,40,112,97,116,104,124,112, - 97,116,104,95,104,111,111,107,115,124,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,41,46,99, - 3,0,0,0,0,0,0,0,4,0,0,0,12,0,0,0, - 67,0,0,0,115,104,0,0,0,124,2,0,115,18,0,116, - 0,0,106,1,0,125,2,0,110,0,0,120,79,0,124,2, - 0,68,93,44,0,125,3,0,121,14,0,124,3,0,124,1, - 0,131,1,0,83,87,113,25,0,4,116,2,0,107,10,0, - 114,68,0,1,1,1,119,25,0,89,113,25,0,88,113,25, - 0,87,116,2,0,100,1,0,106,3,0,124,1,0,131,1, - 0,100,2,0,124,1,0,131,1,1,130,1,0,100,3,0, - 83,40,4,0,0,0,117,113,0,0,0,83,101,97,114,99, - 104,32,115,101,113,117,101,110,99,101,32,111,102,32,104,111, - 111,107,115,32,102,111,114,32,97,32,102,105,110,100,101,114, - 32,102,111,114,32,39,112,97,116,104,39,46,10,10,32,32, - 32,32,32,32,32,32,73,102,32,39,104,111,111,107,115,39, - 32,105,115,32,102,97,108,115,101,32,116,104,101,110,32,117, - 115,101,32,115,121,115,46,112,97,116,104,95,104,111,111,107, - 115,46,10,10,32,32,32,32,32,32,32,32,117,26,0,0, - 0,110,111,32,112,97,116,104,32,104,111,111,107,32,102,111, - 117,110,100,32,102,111,114,32,123,48,125,117,4,0,0,0, - 112,97,116,104,78,40,4,0,0,0,117,3,0,0,0,115, - 121,115,117,10,0,0,0,112,97,116,104,95,104,111,111,107, - 115,117,11,0,0,0,73,109,112,111,114,116,69,114,114,111, - 114,117,6,0,0,0,102,111,114,109,97,116,40,4,0,0, - 0,117,3,0,0,0,99,108,115,117,4,0,0,0,112,97, - 116,104,117,5,0,0,0,104,111,111,107,115,117,4,0,0, - 0,104,111,111,107,40,0,0,0,0,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,11,0,0,0,95,112,97,116,104,95,104,111,111,107, - 115,185,2,0,0,115,18,0,0,0,0,7,6,1,12,1, - 13,1,3,1,14,1,13,1,12,2,18,1,117,22,0,0, - 0,80,97,116,104,70,105,110,100,101,114,46,95,112,97,116, - 104,95,104,111,111,107,115,99,3,0,0,0,0,0,0,0, - 4,0,0,0,12,0,0,0,67,0,0,0,115,137,0,0, - 0,124,1,0,100,1,0,107,2,0,114,21,0,100,2,0, - 125,1,0,110,0,0,121,17,0,116,0,0,106,1,0,124, - 1,0,25,125,3,0,87,110,46,0,4,116,2,0,107,10, - 0,114,86,0,1,1,1,124,0,0,106,3,0,124,1,0, - 131,1,0,125,3,0,124,3,0,116,0,0,106,1,0,124, - 1,0,60,89,110,47,0,88,124,3,0,100,3,0,107,8, - 0,114,133,0,124,2,0,114,133,0,124,2,0,124,1,0, - 131,1,0,125,3,0,124,3,0,116,0,0,106,1,0,124, - 1,0,60,110,0,0,124,3,0,83,40,4,0,0,0,117, - 199,1,0,0,71,101,116,32,116,104,101,32,102,105,110,100, - 101,114,32,102,111,114,32,116,104,101,32,112,97,116,104,32, - 102,114,111,109,32,115,121,115,46,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,46,10,10,32, - 32,32,32,32,32,32,32,73,102,32,116,104,101,32,112,97, - 116,104,32,105,115,32,110,111,116,32,105,110,32,116,104,101, - 32,99,97,99,104,101,44,32,102,105,110,100,32,116,104,101, - 32,97,112,112,114,111,112,114,105,97,116,101,32,102,105,110, - 100,101,114,32,97,110,100,32,99,97,99,104,101,10,32,32, - 32,32,32,32,32,32,105,116,46,32,73,102,32,78,111,110, - 101,32,105,115,32,99,97,99,104,101,100,44,32,103,101,116, - 32,116,104,101,32,100,101,102,97,117,108,116,32,102,105,110, - 100,101,114,32,97,110,100,32,99,97,99,104,101,32,116,104, - 97,116,10,32,32,32,32,32,32,32,32,40,105,102,32,97, - 112,112,108,105,99,97,98,108,101,41,46,10,10,32,32,32, - 32,32,32,32,32,66,101,99,97,117,115,101,32,111,102,32, - 78,117,108,108,73,109,112,111,114,116,101,114,44,32,115,111, - 109,101,32,102,105,110,100,101,114,32,115,104,111,117,108,100, - 32,98,101,32,114,101,116,117,114,110,101,100,46,32,84,104, - 101,32,111,110,108,121,10,32,32,32,32,32,32,32,32,101, - 120,112,108,105,99,105,116,32,102,97,105,108,32,99,97,115, - 101,32,105,115,32,105,102,32,78,111,110,101,32,105,115,32, - 99,97,99,104,101,100,32,98,117,116,32,116,104,101,32,112, - 97,116,104,32,99,97,110,110,111,116,32,98,101,32,117,115, - 101,100,32,102,111,114,10,32,32,32,32,32,32,32,32,116, - 104,101,32,100,101,102,97,117,108,116,32,104,111,111,107,44, - 32,102,111,114,32,119,104,105,99,104,32,73,109,112,111,114, - 116,69,114,114,111,114,32,105,115,32,114,97,105,115,101,100, - 46,10,10,32,32,32,32,32,32,32,32,117,0,0,0,0, - 117,1,0,0,0,46,78,40,5,0,0,0,117,3,0,0, - 0,115,121,115,117,19,0,0,0,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,117,8,0,0, - 0,75,101,121,69,114,114,111,114,117,11,0,0,0,95,112, - 97,116,104,95,104,111,111,107,115,117,4,0,0,0,78,111, - 110,101,40,4,0,0,0,117,3,0,0,0,99,108,115,117, - 4,0,0,0,112,97,116,104,117,7,0,0,0,100,101,102, - 97,117,108,116,117,6,0,0,0,102,105,110,100,101,114,40, + 101,114,46,105,115,95,112,97,99,107,97,103,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,115,4,0,0,0,100,1,0,83,40,2,0,0,0, + 117,63,0,0,0,82,101,116,117,114,110,32,78,111,110,101, + 32,97,115,32,97,110,32,101,120,116,101,110,115,105,111,110, + 32,109,111,100,117,108,101,32,99,97,110,110,111,116,32,99, + 114,101,97,116,101,32,97,32,99,111,100,101,32,111,98,106, + 101,99,116,46,78,40,1,0,0,0,117,4,0,0,0,78, + 111,110,101,40,2,0,0,0,117,4,0,0,0,115,101,108, + 102,117,8,0,0,0,102,117,108,108,110,97,109,101,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,8,0,0,0,103, + 101,116,95,99,111,100,101,178,2,0,0,115,2,0,0,0, + 0,3,117,29,0,0,0,95,69,120,116,101,110,115,105,111, + 110,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95, + 99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, + 0,83,40,2,0,0,0,117,53,0,0,0,82,101,116,117, + 114,110,32,78,111,110,101,32,97,115,32,101,120,116,101,110, + 115,105,111,110,32,109,111,100,117,108,101,115,32,104,97,118, + 101,32,110,111,32,115,111,117,114,99,101,32,99,111,100,101, + 46,78,40,1,0,0,0,117,4,0,0,0,78,111,110,101, + 40,2,0,0,0,117,4,0,0,0,115,101,108,102,117,8, + 0,0,0,102,117,108,108,110,97,109,101,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,10,0,0,0,103,101,116,95, + 115,111,117,114,99,101,183,2,0,0,115,2,0,0,0,0, + 3,117,31,0,0,0,95,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,115, + 111,117,114,99,101,78,40,12,0,0,0,117,8,0,0,0, + 95,95,110,97,109,101,95,95,117,10,0,0,0,95,95,109, + 111,100,117,108,101,95,95,117,12,0,0,0,95,95,113,117, + 97,108,110,97,109,101,95,95,117,7,0,0,0,95,95,100, + 111,99,95,95,117,8,0,0,0,95,95,105,110,105,116,95, + 95,117,11,0,0,0,95,99,104,101,99,107,95,110,97,109, + 101,117,11,0,0,0,115,101,116,95,112,97,99,107,97,103, + 101,117,10,0,0,0,115,101,116,95,108,111,97,100,101,114, + 117,11,0,0,0,108,111,97,100,95,109,111,100,117,108,101, + 117,10,0,0,0,105,115,95,112,97,99,107,97,103,101,117, + 8,0,0,0,103,101,116,95,99,111,100,101,117,10,0,0, + 0,103,101,116,95,115,111,117,114,99,101,40,1,0,0,0, + 117,10,0,0,0,95,95,108,111,99,97,108,115,95,95,40, 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, 95,98,111,111,116,115,116,114,97,112,62,117,20,0,0,0, - 95,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, - 97,99,104,101,203,2,0,0,115,22,0,0,0,0,13,12, - 1,9,1,3,1,17,1,13,1,15,1,18,2,18,2,12, - 1,16,1,117,31,0,0,0,80,97,116,104,70,105,110,100, - 101,114,46,95,112,97,116,104,95,105,109,112,111,114,116,101, - 114,95,99,97,99,104,101,99,3,0,0,0,0,0,0,0, - 6,0,0,0,12,0,0,0,67,0,0,0,115,120,0,0, - 0,124,2,0,115,18,0,116,0,0,106,1,0,125,2,0, - 110,0,0,120,95,0,124,2,0,68,93,83,0,125,3,0, - 121,19,0,124,0,0,106,2,0,124,3,0,131,1,0,125, - 4,0,87,110,21,0,4,116,3,0,107,10,0,114,73,0, - 1,1,1,119,25,0,89,110,1,0,88,124,4,0,114,25, - 0,124,4,0,106,4,0,124,1,0,131,1,0,125,5,0, - 124,5,0,114,108,0,124,5,0,83,113,25,0,113,25,0, - 87,100,1,0,83,100,1,0,83,40,2,0,0,0,117,98, - 0,0,0,70,105,110,100,32,116,104,101,32,109,111,100,117, - 108,101,32,111,110,32,115,121,115,46,112,97,116,104,32,111, - 114,32,39,112,97,116,104,39,32,98,97,115,101,100,32,111, - 110,32,115,121,115,46,112,97,116,104,95,104,111,111,107,115, - 32,97,110,100,10,32,32,32,32,32,32,32,32,115,121,115, - 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, - 97,99,104,101,46,78,40,6,0,0,0,117,3,0,0,0, - 115,121,115,117,4,0,0,0,112,97,116,104,117,20,0,0, - 0,95,112,97,116,104,95,105,109,112,111,114,116,101,114,95, - 99,97,99,104,101,117,11,0,0,0,73,109,112,111,114,116, - 69,114,114,111,114,117,11,0,0,0,102,105,110,100,95,109, - 111,100,117,108,101,117,4,0,0,0,78,111,110,101,40,6, - 0,0,0,117,3,0,0,0,99,108,115,117,8,0,0,0, - 102,117,108,108,110,97,109,101,117,4,0,0,0,112,97,116, - 104,117,5,0,0,0,101,110,116,114,121,117,6,0,0,0, - 102,105,110,100,101,114,117,6,0,0,0,108,111,97,100,101, + 95,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, + 97,100,101,114,146,2,0,0,115,16,0,0,0,16,6,6, + 2,12,4,3,1,3,1,24,13,18,5,18,5,117,20,0, + 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,99,1,0,0,0,0,0,0,0,1, + 0,0,0,4,0,0,0,66,0,0,0,115,89,0,0,0, + 124,0,0,69,101,0,0,90,1,0,100,0,0,90,2,0, + 100,1,0,90,3,0,101,4,0,100,8,0,100,2,0,100, + 3,0,132,1,0,131,1,0,90,6,0,101,4,0,100,8, + 0,100,4,0,100,5,0,132,1,0,131,1,0,90,7,0, + 101,4,0,100,8,0,100,6,0,100,7,0,132,1,0,131, + 1,0,90,8,0,100,8,0,83,40,9,0,0,0,117,10, + 0,0,0,80,97,116,104,70,105,110,100,101,114,117,63,0, + 0,0,77,101,116,97,32,112,97,116,104,32,102,105,110,100, + 101,114,32,102,111,114,32,115,121,115,46,40,112,97,116,104, + 124,112,97,116,104,95,104,111,111,107,115,124,112,97,116,104, + 95,105,109,112,111,114,116,101,114,95,99,97,99,104,101,41, + 46,99,3,0,0,0,0,0,0,0,4,0,0,0,12,0, + 0,0,67,0,0,0,115,104,0,0,0,124,2,0,115,18, + 0,116,0,0,106,1,0,125,2,0,110,0,0,120,79,0, + 124,2,0,68,93,44,0,125,3,0,121,14,0,124,3,0, + 124,1,0,131,1,0,83,87,113,25,0,4,116,2,0,107, + 10,0,114,68,0,1,1,1,119,25,0,89,113,25,0,88, + 113,25,0,87,116,2,0,100,1,0,106,3,0,124,1,0, + 131,1,0,100,2,0,124,1,0,131,1,1,130,1,0,100, + 3,0,83,40,4,0,0,0,117,113,0,0,0,83,101,97, + 114,99,104,32,115,101,113,117,101,110,99,101,32,111,102,32, + 104,111,111,107,115,32,102,111,114,32,97,32,102,105,110,100, + 101,114,32,102,111,114,32,39,112,97,116,104,39,46,10,10, + 32,32,32,32,32,32,32,32,73,102,32,39,104,111,111,107, + 115,39,32,105,115,32,102,97,108,115,101,32,116,104,101,110, + 32,117,115,101,32,115,121,115,46,112,97,116,104,95,104,111, + 111,107,115,46,10,10,32,32,32,32,32,32,32,32,117,26, + 0,0,0,110,111,32,112,97,116,104,32,104,111,111,107,32, + 102,111,117,110,100,32,102,111,114,32,123,48,125,117,4,0, + 0,0,112,97,116,104,78,40,4,0,0,0,117,3,0,0, + 0,115,121,115,117,10,0,0,0,112,97,116,104,95,104,111, + 111,107,115,117,11,0,0,0,73,109,112,111,114,116,69,114, + 114,111,114,117,6,0,0,0,102,111,114,109,97,116,40,4, + 0,0,0,117,3,0,0,0,99,108,115,117,4,0,0,0, + 112,97,116,104,117,5,0,0,0,104,111,111,107,115,117,4, + 0,0,0,104,111,111,107,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,11,0,0,0,95,112,97,116,104,95,104,111, + 111,107,115,195,2,0,0,115,18,0,0,0,0,7,6,1, + 12,1,13,1,3,1,14,1,13,1,12,2,18,1,117,22, + 0,0,0,80,97,116,104,70,105,110,100,101,114,46,95,112, + 97,116,104,95,104,111,111,107,115,99,3,0,0,0,0,0, + 0,0,4,0,0,0,12,0,0,0,67,0,0,0,115,137, + 0,0,0,124,1,0,100,1,0,107,2,0,114,21,0,100, + 2,0,125,1,0,110,0,0,121,17,0,116,0,0,106,1, + 0,124,1,0,25,125,3,0,87,110,46,0,4,116,2,0, + 107,10,0,114,86,0,1,1,1,124,0,0,106,3,0,124, + 1,0,131,1,0,125,3,0,124,3,0,116,0,0,106,1, + 0,124,1,0,60,89,110,47,0,88,124,3,0,100,3,0, + 107,8,0,114,133,0,124,2,0,114,133,0,124,2,0,124, + 1,0,131,1,0,125,3,0,124,3,0,116,0,0,106,1, + 0,124,1,0,60,110,0,0,124,3,0,83,40,4,0,0, + 0,117,199,1,0,0,71,101,116,32,116,104,101,32,102,105, + 110,100,101,114,32,102,111,114,32,116,104,101,32,112,97,116, + 104,32,102,114,111,109,32,115,121,115,46,112,97,116,104,95, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,46,10, + 10,32,32,32,32,32,32,32,32,73,102,32,116,104,101,32, + 112,97,116,104,32,105,115,32,110,111,116,32,105,110,32,116, + 104,101,32,99,97,99,104,101,44,32,102,105,110,100,32,116, + 104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,102, + 105,110,100,101,114,32,97,110,100,32,99,97,99,104,101,10, + 32,32,32,32,32,32,32,32,105,116,46,32,73,102,32,78, + 111,110,101,32,105,115,32,99,97,99,104,101,100,44,32,103, + 101,116,32,116,104,101,32,100,101,102,97,117,108,116,32,102, + 105,110,100,101,114,32,97,110,100,32,99,97,99,104,101,32, + 116,104,97,116,10,32,32,32,32,32,32,32,32,40,105,102, + 32,97,112,112,108,105,99,97,98,108,101,41,46,10,10,32, + 32,32,32,32,32,32,32,66,101,99,97,117,115,101,32,111, + 102,32,78,117,108,108,73,109,112,111,114,116,101,114,44,32, + 115,111,109,101,32,102,105,110,100,101,114,32,115,104,111,117, + 108,100,32,98,101,32,114,101,116,117,114,110,101,100,46,32, + 84,104,101,32,111,110,108,121,10,32,32,32,32,32,32,32, + 32,101,120,112,108,105,99,105,116,32,102,97,105,108,32,99, + 97,115,101,32,105,115,32,105,102,32,78,111,110,101,32,105, + 115,32,99,97,99,104,101,100,32,98,117,116,32,116,104,101, + 32,112,97,116,104,32,99,97,110,110,111,116,32,98,101,32, + 117,115,101,100,32,102,111,114,10,32,32,32,32,32,32,32, + 32,116,104,101,32,100,101,102,97,117,108,116,32,104,111,111, + 107,44,32,102,111,114,32,119,104,105,99,104,32,73,109,112, + 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, + 101,100,46,10,10,32,32,32,32,32,32,32,32,117,0,0, + 0,0,117,1,0,0,0,46,78,40,5,0,0,0,117,3, + 0,0,0,115,121,115,117,19,0,0,0,112,97,116,104,95, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,117,8, + 0,0,0,75,101,121,69,114,114,111,114,117,11,0,0,0, + 95,112,97,116,104,95,104,111,111,107,115,117,4,0,0,0, + 78,111,110,101,40,4,0,0,0,117,3,0,0,0,99,108, + 115,117,4,0,0,0,112,97,116,104,117,7,0,0,0,100, + 101,102,97,117,108,116,117,6,0,0,0,102,105,110,100,101, 114,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,11,0, - 0,0,102,105,110,100,95,109,111,100,117,108,101,230,2,0, - 0,115,24,0,0,0,0,4,6,1,12,1,13,1,3,1, - 19,1,13,1,8,1,6,1,15,1,6,1,11,2,117,22, - 0,0,0,80,97,116,104,70,105,110,100,101,114,46,102,105, - 110,100,95,109,111,100,117,108,101,78,40,9,0,0,0,117, - 8,0,0,0,95,95,110,97,109,101,95,95,117,10,0,0, - 0,95,95,109,111,100,117,108,101,95,95,117,12,0,0,0, - 95,95,113,117,97,108,110,97,109,101,95,95,117,7,0,0, - 0,95,95,100,111,99,95,95,117,11,0,0,0,99,108,97, - 115,115,109,101,116,104,111,100,117,4,0,0,0,78,111,110, - 101,117,11,0,0,0,95,112,97,116,104,95,104,111,111,107, - 115,117,20,0,0,0,95,112,97,116,104,95,105,109,112,111, - 114,116,101,114,95,99,97,99,104,101,117,11,0,0,0,102, - 105,110,100,95,109,111,100,117,108,101,40,1,0,0,0,117, - 10,0,0,0,95,95,108,111,99,97,108,115,95,95,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,80, - 97,116,104,70,105,110,100,101,114,181,2,0,0,115,14,0, - 0,0,16,2,6,2,3,1,18,17,3,1,18,26,3,1, - 117,10,0,0,0,80,97,116,104,70,105,110,100,101,114,99, - 1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, - 66,0,0,0,115,74,0,0,0,124,0,0,69,101,0,0, - 90,1,0,100,0,0,90,2,0,100,1,0,90,3,0,100, - 2,0,100,3,0,132,0,0,90,4,0,100,4,0,100,5, - 0,132,0,0,90,5,0,100,6,0,100,7,0,132,0,0, - 90,6,0,100,8,0,100,9,0,132,0,0,90,7,0,100, - 10,0,83,40,11,0,0,0,117,11,0,0,0,95,70,105, - 108,101,70,105,110,100,101,114,117,171,0,0,0,70,105,108, - 101,45,98,97,115,101,100,32,102,105,110,100,101,114,46,10, - 10,32,32,32,32,67,111,110,115,116,114,117,99,116,111,114, - 32,116,97,107,101,115,32,97,32,108,105,115,116,32,111,102, - 32,111,98,106,101,99,116,115,32,100,101,116,97,105,108,105, - 110,103,32,119,104,97,116,32,102,105,108,101,32,101,120,116, - 101,110,115,105,111,110,115,32,116,104,101,105,114,10,32,32, - 32,32,108,111,97,100,101,114,32,115,117,112,112,111,114,116, - 115,32,97,108,111,110,103,32,119,105,116,104,32,119,104,101, - 116,104,101,114,32,105,116,32,99,97,110,32,98,101,32,117, - 115,101,100,32,102,111,114,32,97,32,112,97,99,107,97,103, - 101,46,10,10,32,32,32,32,99,2,0,0,0,0,0,0, - 0,5,0,0,0,5,0,0,0,7,0,0,0,115,181,0, - 0,0,103,0,0,125,3,0,103,0,0,125,4,0,120,96, - 0,124,2,0,68,93,88,0,137,0,0,124,4,0,106,0, - 0,135,0,0,102,1,0,100,1,0,100,2,0,134,0,0, - 136,0,0,106,1,0,68,131,1,0,131,1,0,1,136,0, - 0,106,2,0,114,19,0,124,3,0,106,0,0,135,0,0, - 102,1,0,100,3,0,100,2,0,134,0,0,136,0,0,106, - 1,0,68,131,1,0,131,1,0,1,113,19,0,113,19,0, - 87,124,3,0,124,0,0,95,3,0,124,4,0,124,0,0, - 95,4,0,124,1,0,112,138,0,100,4,0,124,0,0,95, - 5,0,100,7,0,124,0,0,95,6,0,116,7,0,131,0, - 0,124,0,0,95,8,0,116,7,0,131,0,0,124,0,0, - 95,9,0,100,6,0,83,40,8,0,0,0,117,31,0,0, - 0,73,110,105,116,105,97,108,105,122,101,32,119,105,116,104, - 32,102,105,110,100,101,114,32,100,101,116,97,105,108,115,46, - 99,1,0,0,0,0,0,0,0,2,0,0,0,3,0,0, - 0,51,0,0,0,115,30,0,0,0,124,0,0,93,20,0, - 125,1,0,124,1,0,136,0,0,106,0,0,102,2,0,86, - 1,113,3,0,100,0,0,83,40,1,0,0,0,78,40,1, - 0,0,0,117,6,0,0,0,108,111,97,100,101,114,40,2, - 0,0,0,117,2,0,0,0,46,48,117,6,0,0,0,115, - 117,102,102,105,120,40,1,0,0,0,117,6,0,0,0,100, - 101,116,97,105,108,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,9,0,0, - 0,60,103,101,110,101,120,112,114,62,7,3,0,0,115,2, - 0,0,0,6,0,117,39,0,0,0,95,70,105,108,101,70, - 105,110,100,101,114,46,95,95,105,110,105,116,95,95,46,60, - 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, - 62,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,51,0,0,0,115,30,0,0,0,124,0,0,93,20, - 0,125,1,0,124,1,0,136,0,0,106,0,0,102,2,0, - 86,1,113,3,0,100,0,0,83,40,1,0,0,0,78,40, - 1,0,0,0,117,6,0,0,0,108,111,97,100,101,114,40, - 2,0,0,0,117,2,0,0,0,46,48,117,6,0,0,0, - 115,117,102,102,105,120,40,1,0,0,0,117,6,0,0,0, - 100,101,116,97,105,108,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,9,0, - 0,0,60,103,101,110,101,120,112,114,62,9,3,0,0,115, - 2,0,0,0,6,1,117,1,0,0,0,46,105,1,0,0, - 0,78,105,255,255,255,255,40,10,0,0,0,117,6,0,0, - 0,101,120,116,101,110,100,117,8,0,0,0,115,117,102,102, - 105,120,101,115,117,17,0,0,0,115,117,112,112,111,114,116, - 115,95,112,97,99,107,97,103,101,115,117,8,0,0,0,112, - 97,99,107,97,103,101,115,117,7,0,0,0,109,111,100,117, - 108,101,115,117,4,0,0,0,112,97,116,104,117,11,0,0, - 0,95,112,97,116,104,95,109,116,105,109,101,117,3,0,0, - 0,115,101,116,117,11,0,0,0,95,112,97,116,104,95,99, - 97,99,104,101,117,19,0,0,0,95,114,101,108,97,120,101, - 100,95,112,97,116,104,95,99,97,99,104,101,40,5,0,0, - 0,117,4,0,0,0,115,101,108,102,117,4,0,0,0,112, - 97,116,104,117,7,0,0,0,100,101,116,97,105,108,115,117, - 8,0,0,0,112,97,99,107,97,103,101,115,117,7,0,0, - 0,109,111,100,117,108,101,115,40,0,0,0,0,40,1,0, - 0,0,117,6,0,0,0,100,101,116,97,105,108,117,29,0, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,20,0, + 0,0,95,112,97,116,104,95,105,109,112,111,114,116,101,114, + 95,99,97,99,104,101,213,2,0,0,115,22,0,0,0,0, + 13,12,1,9,1,3,1,17,1,13,1,15,1,18,2,18, + 2,12,1,16,1,117,31,0,0,0,80,97,116,104,70,105, + 110,100,101,114,46,95,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,99,3,0,0,0,0,0, + 0,0,6,0,0,0,12,0,0,0,67,0,0,0,115,120, + 0,0,0,124,2,0,115,18,0,116,0,0,106,1,0,125, + 2,0,110,0,0,120,95,0,124,2,0,68,93,83,0,125, + 3,0,121,19,0,124,0,0,106,2,0,124,3,0,131,1, + 0,125,4,0,87,110,21,0,4,116,3,0,107,10,0,114, + 73,0,1,1,1,119,25,0,89,110,1,0,88,124,4,0, + 114,25,0,124,4,0,106,4,0,124,1,0,131,1,0,125, + 5,0,124,5,0,114,108,0,124,5,0,83,113,25,0,113, + 25,0,87,100,1,0,83,100,1,0,83,40,2,0,0,0, + 117,98,0,0,0,70,105,110,100,32,116,104,101,32,109,111, + 100,117,108,101,32,111,110,32,115,121,115,46,112,97,116,104, + 32,111,114,32,39,112,97,116,104,39,32,98,97,115,101,100, + 32,111,110,32,115,121,115,46,112,97,116,104,95,104,111,111, + 107,115,32,97,110,100,10,32,32,32,32,32,32,32,32,115, + 121,115,46,112,97,116,104,95,105,109,112,111,114,116,101,114, + 95,99,97,99,104,101,46,78,40,6,0,0,0,117,3,0, + 0,0,115,121,115,117,4,0,0,0,112,97,116,104,117,20, + 0,0,0,95,112,97,116,104,95,105,109,112,111,114,116,101, + 114,95,99,97,99,104,101,117,11,0,0,0,73,109,112,111, + 114,116,69,114,114,111,114,117,11,0,0,0,102,105,110,100, + 95,109,111,100,117,108,101,117,4,0,0,0,78,111,110,101, + 40,6,0,0,0,117,3,0,0,0,99,108,115,117,8,0, + 0,0,102,117,108,108,110,97,109,101,117,4,0,0,0,112, + 97,116,104,117,5,0,0,0,101,110,116,114,121,117,6,0, + 0,0,102,105,110,100,101,114,117,6,0,0,0,108,111,97, + 100,101,114,40,0,0,0,0,40,0,0,0,0,117,29,0, 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 8,0,0,0,95,95,105,110,105,116,95,95,2,3,0,0, - 115,26,0,0,0,0,2,6,1,6,1,13,1,35,1,9, - 1,21,1,21,1,9,1,9,2,15,1,9,1,12,1,117, - 20,0,0,0,95,70,105,108,101,70,105,110,100,101,114,46, - 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, - 0,1,0,0,0,2,0,0,0,67,0,0,0,115,13,0, - 0,0,100,3,0,124,0,0,95,0,0,100,2,0,83,40, - 4,0,0,0,117,31,0,0,0,73,110,118,97,108,105,100, - 97,116,101,32,116,104,101,32,100,105,114,101,99,116,111,114, - 121,32,109,116,105,109,101,46,105,1,0,0,0,78,105,255, - 255,255,255,40,1,0,0,0,117,11,0,0,0,95,112,97, - 116,104,95,109,116,105,109,101,40,1,0,0,0,117,4,0, - 0,0,115,101,108,102,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,17,0,0,0,105,110,118,97,108,105,100,97,116, - 101,95,99,97,99,104,101,115,19,3,0,0,115,2,0,0, - 0,0,2,117,29,0,0,0,95,70,105,108,101,70,105,110, - 100,101,114,46,105,110,118,97,108,105,100,97,116,101,95,99, - 97,99,104,101,115,99,2,0,0,0,0,0,0,0,12,0, - 0,0,13,0,0,0,67,0,0,0,115,151,1,0,0,124, - 1,0,106,0,0,100,1,0,131,1,0,100,2,0,25,125, - 2,0,121,25,0,116,1,0,106,2,0,124,0,0,106,3, - 0,131,1,0,106,4,0,125,3,0,87,110,24,0,4,116, - 5,0,107,10,0,114,70,0,1,1,1,100,6,0,125,3, - 0,89,110,1,0,88,124,3,0,124,0,0,106,6,0,107, - 3,0,114,108,0,124,0,0,106,7,0,131,0,0,1,124, - 3,0,124,0,0,95,6,0,110,0,0,116,8,0,131,0, - 0,114,141,0,124,0,0,106,9,0,125,4,0,124,2,0, - 106,10,0,131,0,0,125,5,0,110,15,0,124,0,0,106, - 11,0,125,4,0,124,2,0,125,5,0,124,5,0,124,4, - 0,107,6,0,114,55,1,116,12,0,124,0,0,106,3,0, - 124,2,0,131,2,0,125,6,0,116,13,0,124,6,0,131, - 1,0,114,55,1,120,107,0,124,0,0,106,14,0,68,93, - 62,0,92,2,0,125,7,0,125,8,0,100,4,0,124,7, - 0,23,125,9,0,116,12,0,124,6,0,124,9,0,131,2, - 0,125,10,0,116,15,0,124,10,0,131,1,0,114,208,0, - 124,8,0,124,1,0,124,10,0,131,2,0,83,113,208,0, - 87,100,5,0,125,11,0,116,16,0,106,17,0,124,11,0, - 106,18,0,124,6,0,131,1,0,116,19,0,131,2,0,1, - 113,55,1,110,0,0,120,89,0,124,0,0,106,20,0,68, - 93,78,0,92,2,0,125,7,0,125,8,0,124,5,0,124, - 7,0,23,124,4,0,107,6,0,114,65,1,116,12,0,124, - 0,0,106,3,0,124,2,0,124,7,0,23,131,2,0,125, - 10,0,116,15,0,124,10,0,131,1,0,114,143,1,124,8, - 0,124,1,0,124,10,0,131,2,0,83,113,65,1,113,65, - 1,87,100,7,0,83,40,8,0,0,0,117,46,0,0,0, - 84,114,121,32,116,111,32,102,105,110,100,32,97,32,108,111, - 97,100,101,114,32,102,111,114,32,116,104,101,32,115,112,101, - 99,105,102,105,101,100,32,109,111,100,117,108,101,46,117,1, - 0,0,0,46,105,2,0,0,0,105,1,0,0,0,117,8, - 0,0,0,95,95,105,110,105,116,95,95,117,44,0,0,0, - 78,111,116,32,105,109,112,111,114,116,105,110,103,32,100,105, - 114,101,99,116,111,114,121,32,123,125,58,32,109,105,115,115, - 105,110,103,32,95,95,105,110,105,116,95,95,105,255,255,255, - 255,78,40,22,0,0,0,117,10,0,0,0,114,112,97,114, - 116,105,116,105,111,110,117,3,0,0,0,95,111,115,117,4, - 0,0,0,115,116,97,116,117,4,0,0,0,112,97,116,104, - 117,8,0,0,0,115,116,95,109,116,105,109,101,117,7,0, - 0,0,79,83,69,114,114,111,114,117,11,0,0,0,95,112, - 97,116,104,95,109,116,105,109,101,117,11,0,0,0,95,102, - 105,108,108,95,99,97,99,104,101,117,11,0,0,0,95,114, - 101,108,97,120,95,99,97,115,101,117,19,0,0,0,95,114, - 101,108,97,120,101,100,95,112,97,116,104,95,99,97,99,104, - 101,117,5,0,0,0,108,111,119,101,114,117,11,0,0,0, - 95,112,97,116,104,95,99,97,99,104,101,117,10,0,0,0, - 95,112,97,116,104,95,106,111,105,110,117,11,0,0,0,95, - 112,97,116,104,95,105,115,100,105,114,117,8,0,0,0,112, - 97,99,107,97,103,101,115,117,12,0,0,0,95,112,97,116, - 104,95,105,115,102,105,108,101,117,9,0,0,0,95,119,97, - 114,110,105,110,103,115,117,4,0,0,0,119,97,114,110,117, - 6,0,0,0,102,111,114,109,97,116,117,13,0,0,0,73, - 109,112,111,114,116,87,97,114,110,105,110,103,117,7,0,0, - 0,109,111,100,117,108,101,115,117,4,0,0,0,78,111,110, - 101,40,12,0,0,0,117,4,0,0,0,115,101,108,102,117, - 8,0,0,0,102,117,108,108,110,97,109,101,117,11,0,0, - 0,116,97,105,108,95,109,111,100,117,108,101,117,5,0,0, - 0,109,116,105,109,101,117,5,0,0,0,99,97,99,104,101, - 117,12,0,0,0,99,97,99,104,101,95,109,111,100,117,108, - 101,117,9,0,0,0,98,97,115,101,95,112,97,116,104,117, - 6,0,0,0,115,117,102,102,105,120,117,6,0,0,0,108, - 111,97,100,101,114,117,13,0,0,0,105,110,105,116,95,102, - 105,108,101,110,97,109,101,117,9,0,0,0,102,117,108,108, - 95,112,97,116,104,117,3,0,0,0,109,115,103,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,11,0,0,0,102,105, - 110,100,95,109,111,100,117,108,101,23,3,0,0,115,58,0, - 0,0,0,2,19,1,3,1,25,1,13,1,11,1,15,1, - 10,1,12,2,9,1,9,1,15,2,9,1,6,2,12,1, - 18,1,12,1,22,1,10,1,15,1,12,1,17,2,6,1, - 31,2,22,1,16,1,22,1,12,1,20,1,117,23,0,0, - 0,95,70,105,108,101,70,105,110,100,101,114,46,102,105,110, - 100,95,109,111,100,117,108,101,99,1,0,0,0,0,0,0, - 0,3,0,0,0,3,0,0,0,67,0,0,0,115,71,0, - 0,0,124,0,0,106,0,0,125,1,0,116,1,0,106,2, - 0,124,1,0,131,1,0,125,2,0,116,3,0,124,2,0, - 131,1,0,124,0,0,95,4,0,116,3,0,100,1,0,100, - 2,0,132,0,0,124,2,0,68,131,1,0,131,1,0,124, - 0,0,95,5,0,100,3,0,83,40,4,0,0,0,117,68, - 0,0,0,70,105,108,108,32,116,104,101,32,99,97,99,104, - 101,32,111,102,32,112,111,116,101,110,116,105,97,108,32,109, - 111,100,117,108,101,115,32,97,110,100,32,112,97,99,107,97, - 103,101,115,32,102,111,114,32,116,104,105,115,32,100,105,114, - 101,99,116,111,114,121,46,99,1,0,0,0,0,0,0,0, - 2,0,0,0,2,0,0,0,115,0,0,0,115,27,0,0, - 0,124,0,0,93,17,0,125,1,0,124,1,0,106,0,0, - 131,0,0,86,1,113,3,0,100,0,0,83,40,1,0,0, - 0,78,40,1,0,0,0,117,5,0,0,0,108,111,119,101, - 114,40,2,0,0,0,117,2,0,0,0,46,48,117,2,0, - 0,0,102,110,40,0,0,0,0,40,0,0,0,0,117,29, - 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,9,0,0,0,60,103,101,110,101,120,112,114,62,67,3, - 0,0,115,2,0,0,0,6,0,117,42,0,0,0,95,70, - 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, - 99,97,99,104,101,46,60,108,111,99,97,108,115,62,46,60, - 103,101,110,101,120,112,114,62,78,40,6,0,0,0,117,4, - 0,0,0,112,97,116,104,117,3,0,0,0,95,111,115,117, - 7,0,0,0,108,105,115,116,100,105,114,117,3,0,0,0, - 115,101,116,117,11,0,0,0,95,112,97,116,104,95,99,97, - 99,104,101,117,19,0,0,0,95,114,101,108,97,120,101,100, - 95,112,97,116,104,95,99,97,99,104,101,40,3,0,0,0, - 117,4,0,0,0,115,101,108,102,117,4,0,0,0,112,97, - 116,104,117,8,0,0,0,99,111,110,116,101,110,116,115,40, + 11,0,0,0,102,105,110,100,95,109,111,100,117,108,101,240, + 2,0,0,115,24,0,0,0,0,4,6,1,12,1,13,1, + 3,1,19,1,13,1,8,1,6,1,15,1,6,1,11,2, + 117,22,0,0,0,80,97,116,104,70,105,110,100,101,114,46, + 102,105,110,100,95,109,111,100,117,108,101,78,40,9,0,0, + 0,117,8,0,0,0,95,95,110,97,109,101,95,95,117,10, + 0,0,0,95,95,109,111,100,117,108,101,95,95,117,12,0, + 0,0,95,95,113,117,97,108,110,97,109,101,95,95,117,7, + 0,0,0,95,95,100,111,99,95,95,117,11,0,0,0,99, + 108,97,115,115,109,101,116,104,111,100,117,4,0,0,0,78, + 111,110,101,117,11,0,0,0,95,112,97,116,104,95,104,111, + 111,107,115,117,20,0,0,0,95,112,97,116,104,95,105,109, + 112,111,114,116,101,114,95,99,97,99,104,101,117,11,0,0, + 0,102,105,110,100,95,109,111,100,117,108,101,40,1,0,0, + 0,117,10,0,0,0,95,95,108,111,99,97,108,115,95,95, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, + 0,80,97,116,104,70,105,110,100,101,114,191,2,0,0,115, + 14,0,0,0,16,2,6,2,3,1,18,17,3,1,18,26, + 3,1,117,10,0,0,0,80,97,116,104,70,105,110,100,101, + 114,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, + 0,0,66,0,0,0,115,74,0,0,0,124,0,0,69,101, + 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, + 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, + 100,5,0,132,0,0,90,5,0,100,6,0,100,7,0,132, + 0,0,90,6,0,100,8,0,100,9,0,132,0,0,90,7, + 0,100,10,0,83,40,11,0,0,0,117,11,0,0,0,95, + 70,105,108,101,70,105,110,100,101,114,117,171,0,0,0,70, + 105,108,101,45,98,97,115,101,100,32,102,105,110,100,101,114, + 46,10,10,32,32,32,32,67,111,110,115,116,114,117,99,116, + 111,114,32,116,97,107,101,115,32,97,32,108,105,115,116,32, + 111,102,32,111,98,106,101,99,116,115,32,100,101,116,97,105, + 108,105,110,103,32,119,104,97,116,32,102,105,108,101,32,101, + 120,116,101,110,115,105,111,110,115,32,116,104,101,105,114,10, + 32,32,32,32,108,111,97,100,101,114,32,115,117,112,112,111, + 114,116,115,32,97,108,111,110,103,32,119,105,116,104,32,119, + 104,101,116,104,101,114,32,105,116,32,99,97,110,32,98,101, + 32,117,115,101,100,32,102,111,114,32,97,32,112,97,99,107, + 97,103,101,46,10,10,32,32,32,32,99,2,0,0,0,0, + 0,0,0,5,0,0,0,5,0,0,0,7,0,0,0,115, + 181,0,0,0,103,0,0,125,3,0,103,0,0,125,4,0, + 120,96,0,124,2,0,68,93,88,0,137,0,0,124,4,0, + 106,0,0,135,0,0,102,1,0,100,1,0,100,2,0,134, + 0,0,136,0,0,106,1,0,68,131,1,0,131,1,0,1, + 136,0,0,106,2,0,114,19,0,124,3,0,106,0,0,135, + 0,0,102,1,0,100,3,0,100,2,0,134,0,0,136,0, + 0,106,1,0,68,131,1,0,131,1,0,1,113,19,0,113, + 19,0,87,124,3,0,124,0,0,95,3,0,124,4,0,124, + 0,0,95,4,0,124,1,0,112,138,0,100,4,0,124,0, + 0,95,5,0,100,7,0,124,0,0,95,6,0,116,7,0, + 131,0,0,124,0,0,95,8,0,116,7,0,131,0,0,124, + 0,0,95,9,0,100,6,0,83,40,8,0,0,0,117,31, + 0,0,0,73,110,105,116,105,97,108,105,122,101,32,119,105, + 116,104,32,102,105,110,100,101,114,32,100,101,116,97,105,108, + 115,46,99,1,0,0,0,0,0,0,0,2,0,0,0,3, + 0,0,0,51,0,0,0,115,30,0,0,0,124,0,0,93, + 20,0,125,1,0,124,1,0,136,0,0,106,0,0,102,2, + 0,86,1,113,3,0,100,0,0,83,40,1,0,0,0,78, + 40,1,0,0,0,117,6,0,0,0,108,111,97,100,101,114, + 40,2,0,0,0,117,2,0,0,0,46,48,117,6,0,0, + 0,115,117,102,102,105,120,40,1,0,0,0,117,6,0,0, + 0,100,101,116,97,105,108,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,9, + 0,0,0,60,103,101,110,101,120,112,114,62,17,3,0,0, + 115,2,0,0,0,6,0,117,39,0,0,0,95,70,105,108, + 101,70,105,110,100,101,114,46,95,95,105,110,105,116,95,95, + 46,60,108,111,99,97,108,115,62,46,60,103,101,110,101,120, + 112,114,62,99,1,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,51,0,0,0,115,30,0,0,0,124,0,0, + 93,20,0,125,1,0,124,1,0,136,0,0,106,0,0,102, + 2,0,86,1,113,3,0,100,0,0,83,40,1,0,0,0, + 78,40,1,0,0,0,117,6,0,0,0,108,111,97,100,101, + 114,40,2,0,0,0,117,2,0,0,0,46,48,117,6,0, + 0,0,115,117,102,102,105,120,40,1,0,0,0,117,6,0, + 0,0,100,101,116,97,105,108,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 9,0,0,0,60,103,101,110,101,120,112,114,62,19,3,0, + 0,115,2,0,0,0,6,1,117,1,0,0,0,46,105,1, + 0,0,0,78,105,255,255,255,255,40,10,0,0,0,117,6, + 0,0,0,101,120,116,101,110,100,117,8,0,0,0,115,117, + 102,102,105,120,101,115,117,17,0,0,0,115,117,112,112,111, + 114,116,115,95,112,97,99,107,97,103,101,115,117,8,0,0, + 0,112,97,99,107,97,103,101,115,117,7,0,0,0,109,111, + 100,117,108,101,115,117,4,0,0,0,112,97,116,104,117,11, + 0,0,0,95,112,97,116,104,95,109,116,105,109,101,117,3, + 0,0,0,115,101,116,117,11,0,0,0,95,112,97,116,104, + 95,99,97,99,104,101,117,19,0,0,0,95,114,101,108,97, + 120,101,100,95,112,97,116,104,95,99,97,99,104,101,40,5, + 0,0,0,117,4,0,0,0,115,101,108,102,117,4,0,0, + 0,112,97,116,104,117,7,0,0,0,100,101,116,97,105,108, + 115,117,8,0,0,0,112,97,99,107,97,103,101,115,117,7, + 0,0,0,109,111,100,117,108,101,115,40,0,0,0,0,40, + 1,0,0,0,117,6,0,0,0,100,101,116,97,105,108,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,8,0,0,0,95,95,105,110,105,116,95,95,12,3, + 0,0,115,26,0,0,0,0,2,6,1,6,1,13,1,35, + 1,9,1,21,1,21,1,9,1,9,2,15,1,9,1,12, + 1,117,20,0,0,0,95,70,105,108,101,70,105,110,100,101, + 114,46,95,95,105,110,105,116,95,95,99,1,0,0,0,0, + 0,0,0,1,0,0,0,2,0,0,0,67,0,0,0,115, + 13,0,0,0,100,3,0,124,0,0,95,0,0,100,2,0, + 83,40,4,0,0,0,117,31,0,0,0,73,110,118,97,108, + 105,100,97,116,101,32,116,104,101,32,100,105,114,101,99,116, + 111,114,121,32,109,116,105,109,101,46,105,1,0,0,0,78, + 105,255,255,255,255,40,1,0,0,0,117,11,0,0,0,95, + 112,97,116,104,95,109,116,105,109,101,40,1,0,0,0,117, + 4,0,0,0,115,101,108,102,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,17,0,0,0,105,110,118,97,108,105,100, + 97,116,101,95,99,97,99,104,101,115,29,3,0,0,115,2, + 0,0,0,0,2,117,29,0,0,0,95,70,105,108,101,70, + 105,110,100,101,114,46,105,110,118,97,108,105,100,97,116,101, + 95,99,97,99,104,101,115,99,2,0,0,0,0,0,0,0, + 12,0,0,0,13,0,0,0,67,0,0,0,115,151,1,0, + 0,124,1,0,106,0,0,100,1,0,131,1,0,100,2,0, + 25,125,2,0,121,25,0,116,1,0,106,2,0,124,0,0, + 106,3,0,131,1,0,106,4,0,125,3,0,87,110,24,0, + 4,116,5,0,107,10,0,114,70,0,1,1,1,100,6,0, + 125,3,0,89,110,1,0,88,124,3,0,124,0,0,106,6, + 0,107,3,0,114,108,0,124,0,0,106,7,0,131,0,0, + 1,124,3,0,124,0,0,95,6,0,110,0,0,116,8,0, + 131,0,0,114,141,0,124,0,0,106,9,0,125,4,0,124, + 2,0,106,10,0,131,0,0,125,5,0,110,15,0,124,0, + 0,106,11,0,125,4,0,124,2,0,125,5,0,124,5,0, + 124,4,0,107,6,0,114,55,1,116,12,0,124,0,0,106, + 3,0,124,2,0,131,2,0,125,6,0,116,13,0,124,6, + 0,131,1,0,114,55,1,120,107,0,124,0,0,106,14,0, + 68,93,62,0,92,2,0,125,7,0,125,8,0,100,4,0, + 124,7,0,23,125,9,0,116,12,0,124,6,0,124,9,0, + 131,2,0,125,10,0,116,15,0,124,10,0,131,1,0,114, + 208,0,124,8,0,124,1,0,124,10,0,131,2,0,83,113, + 208,0,87,100,5,0,125,11,0,116,16,0,106,17,0,124, + 11,0,106,18,0,124,6,0,131,1,0,116,19,0,131,2, + 0,1,113,55,1,110,0,0,120,89,0,124,0,0,106,20, + 0,68,93,78,0,92,2,0,125,7,0,125,8,0,124,5, + 0,124,7,0,23,124,4,0,107,6,0,114,65,1,116,12, + 0,124,0,0,106,3,0,124,2,0,124,7,0,23,131,2, + 0,125,10,0,116,15,0,124,10,0,131,1,0,114,143,1, + 124,8,0,124,1,0,124,10,0,131,2,0,83,113,65,1, + 113,65,1,87,100,7,0,83,40,8,0,0,0,117,46,0, + 0,0,84,114,121,32,116,111,32,102,105,110,100,32,97,32, + 108,111,97,100,101,114,32,102,111,114,32,116,104,101,32,115, + 112,101,99,105,102,105,101,100,32,109,111,100,117,108,101,46, + 117,1,0,0,0,46,105,2,0,0,0,105,1,0,0,0, + 117,8,0,0,0,95,95,105,110,105,116,95,95,117,44,0, + 0,0,78,111,116,32,105,109,112,111,114,116,105,110,103,32, + 100,105,114,101,99,116,111,114,121,32,123,125,58,32,109,105, + 115,115,105,110,103,32,95,95,105,110,105,116,95,95,105,255, + 255,255,255,78,40,22,0,0,0,117,10,0,0,0,114,112, + 97,114,116,105,116,105,111,110,117,3,0,0,0,95,111,115, + 117,4,0,0,0,115,116,97,116,117,4,0,0,0,112,97, + 116,104,117,8,0,0,0,115,116,95,109,116,105,109,101,117, + 7,0,0,0,79,83,69,114,114,111,114,117,11,0,0,0, + 95,112,97,116,104,95,109,116,105,109,101,117,11,0,0,0, + 95,102,105,108,108,95,99,97,99,104,101,117,11,0,0,0, + 95,114,101,108,97,120,95,99,97,115,101,117,19,0,0,0, + 95,114,101,108,97,120,101,100,95,112,97,116,104,95,99,97, + 99,104,101,117,5,0,0,0,108,111,119,101,114,117,11,0, + 0,0,95,112,97,116,104,95,99,97,99,104,101,117,10,0, + 0,0,95,112,97,116,104,95,106,111,105,110,117,11,0,0, + 0,95,112,97,116,104,95,105,115,100,105,114,117,8,0,0, + 0,112,97,99,107,97,103,101,115,117,12,0,0,0,95,112, + 97,116,104,95,105,115,102,105,108,101,117,9,0,0,0,95, + 119,97,114,110,105,110,103,115,117,4,0,0,0,119,97,114, + 110,117,6,0,0,0,102,111,114,109,97,116,117,13,0,0, + 0,73,109,112,111,114,116,87,97,114,110,105,110,103,117,7, + 0,0,0,109,111,100,117,108,101,115,117,4,0,0,0,78, + 111,110,101,40,12,0,0,0,117,4,0,0,0,115,101,108, + 102,117,8,0,0,0,102,117,108,108,110,97,109,101,117,11, + 0,0,0,116,97,105,108,95,109,111,100,117,108,101,117,5, + 0,0,0,109,116,105,109,101,117,5,0,0,0,99,97,99, + 104,101,117,12,0,0,0,99,97,99,104,101,95,109,111,100, + 117,108,101,117,9,0,0,0,98,97,115,101,95,112,97,116, + 104,117,6,0,0,0,115,117,102,102,105,120,117,6,0,0, + 0,108,111,97,100,101,114,117,13,0,0,0,105,110,105,116, + 95,102,105,108,101,110,97,109,101,117,9,0,0,0,102,117, + 108,108,95,112,97,116,104,117,3,0,0,0,109,115,103,40, 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, - 95,102,105,108,108,95,99,97,99,104,101,60,3,0,0,115, - 8,0,0,0,0,2,9,1,15,3,15,1,117,23,0,0, - 0,95,70,105,108,101,70,105,110,100,101,114,46,95,102,105, - 108,108,95,99,97,99,104,101,78,40,8,0,0,0,117,8, + 102,105,110,100,95,109,111,100,117,108,101,33,3,0,0,115, + 58,0,0,0,0,2,19,1,3,1,25,1,13,1,11,1, + 15,1,10,1,12,2,9,1,9,1,15,2,9,1,6,2, + 12,1,18,1,12,1,22,1,10,1,15,1,12,1,17,2, + 6,1,31,2,22,1,16,1,22,1,12,1,20,1,117,23, + 0,0,0,95,70,105,108,101,70,105,110,100,101,114,46,102, + 105,110,100,95,109,111,100,117,108,101,99,1,0,0,0,0, + 0,0,0,3,0,0,0,3,0,0,0,67,0,0,0,115, + 71,0,0,0,124,0,0,106,0,0,125,1,0,116,1,0, + 106,2,0,124,1,0,131,1,0,125,2,0,116,3,0,124, + 2,0,131,1,0,124,0,0,95,4,0,116,3,0,100,1, + 0,100,2,0,132,0,0,124,2,0,68,131,1,0,131,1, + 0,124,0,0,95,5,0,100,3,0,83,40,4,0,0,0, + 117,68,0,0,0,70,105,108,108,32,116,104,101,32,99,97, + 99,104,101,32,111,102,32,112,111,116,101,110,116,105,97,108, + 32,109,111,100,117,108,101,115,32,97,110,100,32,112,97,99, + 107,97,103,101,115,32,102,111,114,32,116,104,105,115,32,100, + 105,114,101,99,116,111,114,121,46,99,1,0,0,0,0,0, + 0,0,2,0,0,0,2,0,0,0,115,0,0,0,115,27, + 0,0,0,124,0,0,93,17,0,125,1,0,124,1,0,106, + 0,0,131,0,0,86,1,113,3,0,100,0,0,83,40,1, + 0,0,0,78,40,1,0,0,0,117,5,0,0,0,108,111, + 119,101,114,40,2,0,0,0,117,2,0,0,0,46,48,117, + 2,0,0,0,102,110,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,9,0,0,0,60,103,101,110,101,120,112,114,62, + 77,3,0,0,115,2,0,0,0,6,0,117,42,0,0,0, + 95,70,105,108,101,70,105,110,100,101,114,46,95,102,105,108, + 108,95,99,97,99,104,101,46,60,108,111,99,97,108,115,62, + 46,60,103,101,110,101,120,112,114,62,78,40,6,0,0,0, + 117,4,0,0,0,112,97,116,104,117,3,0,0,0,95,111, + 115,117,7,0,0,0,108,105,115,116,100,105,114,117,3,0, + 0,0,115,101,116,117,11,0,0,0,95,112,97,116,104,95, + 99,97,99,104,101,117,19,0,0,0,95,114,101,108,97,120, + 101,100,95,112,97,116,104,95,99,97,99,104,101,40,3,0, + 0,0,117,4,0,0,0,115,101,108,102,117,4,0,0,0, + 112,97,116,104,117,8,0,0,0,99,111,110,116,101,110,116, + 115,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,11,0, + 0,0,95,102,105,108,108,95,99,97,99,104,101,70,3,0, + 0,115,8,0,0,0,0,2,9,1,15,3,15,1,117,23, + 0,0,0,95,70,105,108,101,70,105,110,100,101,114,46,95, + 102,105,108,108,95,99,97,99,104,101,78,40,8,0,0,0, + 117,8,0,0,0,95,95,110,97,109,101,95,95,117,10,0, + 0,0,95,95,109,111,100,117,108,101,95,95,117,12,0,0, + 0,95,95,113,117,97,108,110,97,109,101,95,95,117,7,0, + 0,0,95,95,100,111,99,95,95,117,8,0,0,0,95,95, + 105,110,105,116,95,95,117,17,0,0,0,105,110,118,97,108, + 105,100,97,116,101,95,99,97,99,104,101,115,117,11,0,0, + 0,102,105,110,100,95,109,111,100,117,108,101,117,11,0,0, + 0,95,102,105,108,108,95,99,97,99,104,101,40,1,0,0, + 0,117,10,0,0,0,95,95,108,111,99,97,108,115,95,95, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,11,0,0, + 0,95,70,105,108,101,70,105,110,100,101,114,3,3,0,0, + 115,10,0,0,0,16,7,6,2,12,17,12,4,12,37,117, + 11,0,0,0,95,70,105,108,101,70,105,110,100,101,114,99, + 1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, + 66,0,0,0,115,44,0,0,0,124,0,0,69,101,0,0, + 90,1,0,100,0,0,90,2,0,101,3,0,90,4,0,100, + 4,0,90,6,0,100,1,0,100,2,0,132,0,0,90,7, + 0,100,3,0,83,40,5,0,0,0,117,20,0,0,0,95, + 83,111,117,114,99,101,70,105,110,100,101,114,68,101,116,97, + 105,108,115,99,1,0,0,0,0,0,0,0,1,0,0,0, + 2,0,0,0,67,0,0,0,115,22,0,0,0,116,0,0, + 116,1,0,106,2,0,131,1,0,124,0,0,95,3,0,100, + 0,0,83,40,1,0,0,0,78,40,4,0,0,0,117,12, + 0,0,0,95,115,117,102,102,105,120,95,108,105,115,116,117, + 4,0,0,0,95,105,109,112,117,9,0,0,0,80,89,95, + 83,79,85,82,67,69,117,8,0,0,0,115,117,102,102,105, + 120,101,115,40,1,0,0,0,117,4,0,0,0,115,101,108, + 102,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, + 0,0,95,95,105,110,105,116,95,95,85,3,0,0,115,2, + 0,0,0,0,1,117,29,0,0,0,95,83,111,117,114,99, + 101,70,105,110,100,101,114,68,101,116,97,105,108,115,46,95, + 95,105,110,105,116,95,95,78,84,40,8,0,0,0,117,8, 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, 95,95,109,111,100,117,108,101,95,95,117,12,0,0,0,95, - 95,113,117,97,108,110,97,109,101,95,95,117,7,0,0,0, - 95,95,100,111,99,95,95,117,8,0,0,0,95,95,105,110, - 105,116,95,95,117,17,0,0,0,105,110,118,97,108,105,100, - 97,116,101,95,99,97,99,104,101,115,117,11,0,0,0,102, - 105,110,100,95,109,111,100,117,108,101,117,11,0,0,0,95, - 102,105,108,108,95,99,97,99,104,101,40,1,0,0,0,117, - 10,0,0,0,95,95,108,111,99,97,108,115,95,95,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,11,0,0,0,95, - 70,105,108,101,70,105,110,100,101,114,249,2,0,0,115,10, - 0,0,0,16,7,6,2,12,17,12,4,12,37,117,11,0, - 0,0,95,70,105,108,101,70,105,110,100,101,114,99,1,0, - 0,0,0,0,0,0,1,0,0,0,2,0,0,0,66,0, - 0,0,115,44,0,0,0,124,0,0,69,101,0,0,90,1, - 0,100,0,0,90,2,0,101,3,0,90,4,0,100,4,0, - 90,6,0,100,1,0,100,2,0,132,0,0,90,7,0,100, - 3,0,83,40,5,0,0,0,117,20,0,0,0,95,83,111, + 95,113,117,97,108,110,97,109,101,95,95,117,17,0,0,0, + 95,83,111,117,114,99,101,70,105,108,101,76,111,97,100,101, + 114,117,6,0,0,0,108,111,97,100,101,114,117,4,0,0, + 0,84,114,117,101,117,17,0,0,0,115,117,112,112,111,114, + 116,115,95,112,97,99,107,97,103,101,115,117,8,0,0,0, + 95,95,105,110,105,116,95,95,40,1,0,0,0,117,10,0, + 0,0,95,95,108,111,99,97,108,115,95,95,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,20,0,0,0,95,83,111, 117,114,99,101,70,105,110,100,101,114,68,101,116,97,105,108, + 115,80,3,0,0,115,6,0,0,0,16,2,6,1,6,2, + 117,20,0,0,0,95,83,111,117,114,99,101,70,105,110,100, + 101,114,68,101,116,97,105,108,115,99,1,0,0,0,0,0, + 0,0,1,0,0,0,2,0,0,0,66,0,0,0,115,44, + 0,0,0,124,0,0,69,101,0,0,90,1,0,100,0,0, + 90,2,0,101,3,0,90,4,0,100,4,0,90,6,0,100, + 1,0,100,2,0,132,0,0,90,7,0,100,3,0,83,40, + 5,0,0,0,117,24,0,0,0,95,83,111,117,114,99,101, + 108,101,115,115,70,105,110,100,101,114,68,101,116,97,105,108, 115,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, 0,0,67,0,0,0,115,22,0,0,0,116,0,0,116,1, 0,106,2,0,131,1,0,124,0,0,95,3,0,100,0,0, 83,40,1,0,0,0,78,40,4,0,0,0,117,12,0,0, - 0,95,115,117,102,102,105,120,95,108,105,115,116,117,3,0, - 0,0,105,109,112,117,9,0,0,0,80,89,95,83,79,85, - 82,67,69,117,8,0,0,0,115,117,102,102,105,120,101,115, - 40,1,0,0,0,117,4,0,0,0,115,101,108,102,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 0,95,115,117,102,102,105,120,95,108,105,115,116,117,4,0, + 0,0,95,105,109,112,117,11,0,0,0,80,89,95,67,79, + 77,80,73,76,69,68,117,8,0,0,0,115,117,102,102,105, + 120,101,115,40,1,0,0,0,117,4,0,0,0,115,101,108, + 102,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, + 0,0,95,95,105,110,105,116,95,95,93,3,0,0,115,2, + 0,0,0,0,1,117,33,0,0,0,95,83,111,117,114,99, + 101,108,101,115,115,70,105,110,100,101,114,68,101,116,97,105, + 108,115,46,95,95,105,110,105,116,95,95,78,84,40,8,0, + 0,0,117,8,0,0,0,95,95,110,97,109,101,95,95,117, + 10,0,0,0,95,95,109,111,100,117,108,101,95,95,117,12, + 0,0,0,95,95,113,117,97,108,110,97,109,101,95,95,117, + 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, + 105,108,101,76,111,97,100,101,114,117,6,0,0,0,108,111, + 97,100,101,114,117,4,0,0,0,84,114,117,101,117,17,0, + 0,0,115,117,112,112,111,114,116,115,95,112,97,99,107,97, + 103,101,115,117,8,0,0,0,95,95,105,110,105,116,95,95, + 40,1,0,0,0,117,10,0,0,0,95,95,108,111,99,97, + 108,115,95,95,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,24,0,0,0,95,83,111,117,114,99,101,108,101,115,115, + 70,105,110,100,101,114,68,101,116,97,105,108,115,88,3,0, + 0,115,6,0,0,0,16,2,6,1,6,2,117,24,0,0, + 0,95,83,111,117,114,99,101,108,101,115,115,70,105,110,100, + 101,114,68,101,116,97,105,108,115,99,1,0,0,0,0,0, + 0,0,1,0,0,0,2,0,0,0,66,0,0,0,115,44, + 0,0,0,124,0,0,69,101,0,0,90,1,0,100,0,0, + 90,2,0,101,3,0,90,4,0,100,4,0,90,6,0,100, + 1,0,100,2,0,132,0,0,90,7,0,100,3,0,83,40, + 5,0,0,0,117,23,0,0,0,95,69,120,116,101,110,115, + 105,111,110,70,105,110,100,101,114,68,101,116,97,105,108,115, + 99,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0, + 0,67,0,0,0,115,22,0,0,0,116,0,0,116,1,0, + 106,2,0,131,1,0,124,0,0,95,3,0,100,0,0,83, + 40,1,0,0,0,78,40,4,0,0,0,117,12,0,0,0, + 95,115,117,102,102,105,120,95,108,105,115,116,117,4,0,0, + 0,95,105,109,112,117,11,0,0,0,67,95,69,88,84,69, + 78,83,73,79,78,117,8,0,0,0,115,117,102,102,105,120, + 101,115,40,1,0,0,0,117,4,0,0,0,115,101,108,102, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,8,0,0, + 0,95,95,105,110,105,116,95,95,102,3,0,0,115,2,0, + 0,0,0,1,117,32,0,0,0,95,69,120,116,101,110,115, + 105,111,110,70,105,110,100,101,114,68,101,116,97,105,108,115, + 46,95,95,105,110,105,116,95,95,78,70,40,8,0,0,0, + 117,8,0,0,0,95,95,110,97,109,101,95,95,117,10,0, + 0,0,95,95,109,111,100,117,108,101,95,95,117,12,0,0, + 0,95,95,113,117,97,108,110,97,109,101,95,95,117,20,0, + 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,117,6,0,0,0,108,111,97,100,101, + 114,117,5,0,0,0,70,97,108,115,101,117,17,0,0,0, + 115,117,112,112,111,114,116,115,95,112,97,99,107,97,103,101, + 115,117,8,0,0,0,95,95,105,110,105,116,95,95,40,1, + 0,0,0,117,10,0,0,0,95,95,108,111,99,97,108,115, + 95,95,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,23, + 0,0,0,95,69,120,116,101,110,115,105,111,110,70,105,110, + 100,101,114,68,101,116,97,105,108,115,97,3,0,0,115,6, + 0,0,0,16,2,6,1,6,2,117,23,0,0,0,95,69, + 120,116,101,110,115,105,111,110,70,105,110,100,101,114,68,101, + 116,97,105,108,115,99,1,0,0,0,0,0,0,0,1,0, + 0,0,5,0,0,0,67,0,0,0,115,62,0,0,0,116, + 0,0,124,0,0,131,1,0,114,40,0,116,1,0,124,0, + 0,116,2,0,131,0,0,116,3,0,131,0,0,116,4,0, + 131,0,0,131,4,0,83,116,5,0,100,1,0,100,2,0, + 124,0,0,131,1,1,130,1,0,100,3,0,83,40,4,0, + 0,0,117,55,0,0,0,73,102,32,116,104,101,32,112,97, + 116,104,32,105,115,32,97,32,100,105,114,101,99,116,111,114, + 121,44,32,114,101,116,117,114,110,32,97,32,102,105,108,101, + 45,98,97,115,101,100,32,102,105,110,100,101,114,46,117,30, + 0,0,0,111,110,108,121,32,100,105,114,101,99,116,111,114, + 105,101,115,32,97,114,101,32,115,117,112,112,111,114,116,101, + 100,117,4,0,0,0,112,97,116,104,78,40,6,0,0,0, + 117,11,0,0,0,95,112,97,116,104,95,105,115,100,105,114, + 117,11,0,0,0,95,70,105,108,101,70,105,110,100,101,114, + 117,23,0,0,0,95,69,120,116,101,110,115,105,111,110,70, + 105,110,100,101,114,68,101,116,97,105,108,115,117,20,0,0, + 0,95,83,111,117,114,99,101,70,105,110,100,101,114,68,101, + 116,97,105,108,115,117,24,0,0,0,95,83,111,117,114,99, + 101,108,101,115,115,70,105,110,100,101,114,68,101,116,97,105, + 108,115,117,11,0,0,0,73,109,112,111,114,116,69,114,114, + 111,114,40,1,0,0,0,117,4,0,0,0,112,97,116,104, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,15,0,0, + 0,95,102,105,108,101,95,112,97,116,104,95,104,111,111,107, + 108,3,0,0,115,10,0,0,0,0,2,12,1,12,1,6, + 1,10,2,117,15,0,0,0,95,102,105,108,101,95,112,97, + 116,104,95,104,111,111,107,99,1,0,0,0,0,0,0,0, + 1,0,0,0,4,0,0,0,2,0,0,0,115,74,0,0, + 0,124,0,0,69,101,0,0,90,1,0,100,0,0,90,2, + 0,100,1,0,90,3,0,101,4,0,135,0,0,102,1,0, + 100,2,0,100,3,0,134,0,0,131,1,0,90,5,0,101, + 4,0,135,0,0,102,1,0,100,4,0,100,5,0,134,0, + 0,131,1,0,90,6,0,135,0,0,83,40,6,0,0,0, + 117,18,0,0,0,95,68,101,102,97,117,108,116,80,97,116, + 104,70,105,110,100,101,114,117,77,0,0,0,83,117,98,99, + 108,97,115,115,32,111,102,32,80,97,116,104,70,105,110,100, + 101,114,32,116,104,97,116,32,105,109,112,108,101,109,101,110, + 116,115,32,105,109,112,108,105,99,105,116,32,115,101,109,97, + 110,116,105,99,115,32,102,111,114,10,32,32,32,32,95,95, + 105,109,112,111,114,116,95,95,46,99,2,0,0,0,0,0, + 0,0,3,0,0,0,11,0,0,0,3,0,0,0,115,79, + 0,0,0,121,20,0,116,0,0,131,0,0,106,1,0,124, + 1,0,131,1,0,83,87,110,52,0,4,116,2,0,107,10, + 0,114,74,0,1,1,1,116,3,0,116,4,0,106,5,0, + 103,2,0,125,2,0,116,0,0,131,0,0,106,1,0,124, + 1,0,124,2,0,131,2,0,83,89,110,1,0,88,100,1, + 0,83,40,2,0,0,0,117,53,0,0,0,83,101,97,114, + 99,104,32,115,121,115,46,112,97,116,104,95,104,111,111,107, + 115,32,97,115,32,119,101,108,108,32,97,115,32,105,109,112, + 108,105,99,105,116,32,112,97,116,104,32,104,111,111,107,115, + 46,78,40,6,0,0,0,117,5,0,0,0,115,117,112,101, + 114,117,11,0,0,0,95,112,97,116,104,95,104,111,111,107, + 115,117,11,0,0,0,73,109,112,111,114,116,69,114,114,111, + 114,117,18,0,0,0,95,68,69,70,65,85,76,84,95,80, + 65,84,72,95,72,79,79,75,117,4,0,0,0,95,105,109, + 112,117,12,0,0,0,78,117,108,108,73,109,112,111,114,116, + 101,114,40,3,0,0,0,117,3,0,0,0,99,108,115,117, + 4,0,0,0,112,97,116,104,117,14,0,0,0,105,109,112, + 108,105,99,105,116,95,104,111,111,107,115,40,1,0,0,0, + 117,10,0,0,0,64,95,95,99,108,97,115,115,95,95,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,11,0,0,0,95,112,97,116,104, + 95,104,111,111,107,115,125,3,0,0,115,10,0,0,0,0, + 3,3,1,20,1,13,1,15,1,117,30,0,0,0,95,68, + 101,102,97,117,108,116,80,97,116,104,70,105,110,100,101,114, + 46,95,112,97,116,104,95,104,111,111,107,115,99,2,0,0, + 0,0,0,0,0,2,0,0,0,3,0,0,0,3,0,0, + 0,115,19,0,0,0,116,0,0,131,0,0,106,1,0,124, + 1,0,116,2,0,131,2,0,83,40,1,0,0,0,117,81, + 0,0,0,85,115,101,32,116,104,101,32,100,101,102,97,117, + 108,116,32,112,97,116,104,32,104,111,111,107,32,119,104,101, + 110,32,78,111,110,101,32,105,115,32,115,116,111,114,101,100, + 32,105,110,10,32,32,32,32,32,32,32,32,115,121,115,46, + 112,97,116,104,95,105,109,112,111,114,116,101,114,95,99,97, + 99,104,101,46,40,3,0,0,0,117,5,0,0,0,115,117, + 112,101,114,117,20,0,0,0,95,112,97,116,104,95,105,109, + 112,111,114,116,101,114,95,99,97,99,104,101,117,18,0,0, + 0,95,68,69,70,65,85,76,84,95,80,65,84,72,95,72, + 79,79,75,40,2,0,0,0,117,3,0,0,0,99,108,115, + 117,4,0,0,0,112,97,116,104,40,1,0,0,0,117,10, + 0,0,0,64,95,95,99,108,97,115,115,95,95,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,20,0,0,0,95,112,97,116,104,95,105, + 109,112,111,114,116,101,114,95,99,97,99,104,101,134,3,0, + 0,115,2,0,0,0,0,4,117,39,0,0,0,95,68,101, + 102,97,117,108,116,80,97,116,104,70,105,110,100,101,114,46, + 95,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, + 97,99,104,101,40,7,0,0,0,117,8,0,0,0,95,95, + 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, + 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, + 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, + 95,95,117,11,0,0,0,99,108,97,115,115,109,101,116,104, + 111,100,117,11,0,0,0,95,112,97,116,104,95,104,111,111, + 107,115,117,20,0,0,0,95,112,97,116,104,95,105,109,112, + 111,114,116,101,114,95,99,97,99,104,101,40,1,0,0,0, + 117,10,0,0,0,95,95,108,111,99,97,108,115,95,95,40, + 0,0,0,0,40,1,0,0,0,117,10,0,0,0,64,95, + 95,99,108,97,115,115,95,95,117,29,0,0,0,60,102,114, 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,8,0,0,0,95, - 95,105,110,105,116,95,95,75,3,0,0,115,2,0,0,0, - 0,1,117,29,0,0,0,95,83,111,117,114,99,101,70,105, - 110,100,101,114,68,101,116,97,105,108,115,46,95,95,105,110, - 105,116,95,95,78,84,40,8,0,0,0,117,8,0,0,0, - 95,95,110,97,109,101,95,95,117,10,0,0,0,95,95,109, - 111,100,117,108,101,95,95,117,12,0,0,0,95,95,113,117, - 97,108,110,97,109,101,95,95,117,17,0,0,0,95,83,111, - 117,114,99,101,70,105,108,101,76,111,97,100,101,114,117,6, - 0,0,0,108,111,97,100,101,114,117,4,0,0,0,84,114, - 117,101,117,17,0,0,0,115,117,112,112,111,114,116,115,95, - 112,97,99,107,97,103,101,115,117,8,0,0,0,95,95,105, - 110,105,116,95,95,40,1,0,0,0,117,10,0,0,0,95, - 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,0, + 98,111,111,116,115,116,114,97,112,62,117,18,0,0,0,95, + 68,101,102,97,117,108,116,80,97,116,104,70,105,110,100,101, + 114,120,3,0,0,115,6,0,0,0,16,3,6,2,24,9, + 117,18,0,0,0,95,68,101,102,97,117,108,116,80,97,116, + 104,70,105,110,100,101,114,99,1,0,0,0,0,0,0,0, + 1,0,0,0,2,0,0,0,66,0,0,0,115,50,0,0, + 0,124,0,0,69,101,0,0,90,1,0,100,0,0,90,2, + 0,100,1,0,90,3,0,100,2,0,100,3,0,132,0,0, + 90,4,0,100,4,0,100,5,0,132,0,0,90,5,0,100, + 6,0,83,40,7,0,0,0,117,18,0,0,0,95,73,109, + 112,111,114,116,76,111,99,107,67,111,110,116,101,120,116,117, + 36,0,0,0,67,111,110,116,101,120,116,32,109,97,110,97, + 103,101,114,32,102,111,114,32,116,104,101,32,105,109,112,111, + 114,116,32,108,111,99,107,46,99,1,0,0,0,0,0,0, + 0,1,0,0,0,1,0,0,0,67,0,0,0,115,14,0, + 0,0,116,0,0,106,1,0,131,0,0,1,100,1,0,83, + 40,2,0,0,0,117,24,0,0,0,65,99,113,117,105,114, + 101,32,116,104,101,32,105,109,112,111,114,116,32,108,111,99, + 107,46,78,40,2,0,0,0,117,4,0,0,0,95,105,109, + 112,117,12,0,0,0,97,99,113,117,105,114,101,95,108,111, + 99,107,40,1,0,0,0,117,4,0,0,0,115,101,108,102, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,9,0,0, + 0,95,95,101,110,116,101,114,95,95,145,3,0,0,115,2, + 0,0,0,0,2,117,28,0,0,0,95,73,109,112,111,114, + 116,76,111,99,107,67,111,110,116,101,120,116,46,95,95,101, + 110,116,101,114,95,95,99,4,0,0,0,0,0,0,0,4, + 0,0,0,1,0,0,0,67,0,0,0,115,14,0,0,0, + 116,0,0,106,1,0,131,0,0,1,100,1,0,83,40,2, + 0,0,0,117,60,0,0,0,82,101,108,101,97,115,101,32, + 116,104,101,32,105,109,112,111,114,116,32,108,111,99,107,32, + 114,101,103,97,114,100,108,101,115,115,32,111,102,32,97,110, + 121,32,114,97,105,115,101,100,32,101,120,99,101,112,116,105, + 111,110,115,46,78,40,2,0,0,0,117,4,0,0,0,95, + 105,109,112,117,12,0,0,0,114,101,108,101,97,115,101,95, + 108,111,99,107,40,4,0,0,0,117,4,0,0,0,115,101, + 108,102,117,8,0,0,0,101,120,99,95,116,121,112,101,117, + 9,0,0,0,101,120,99,95,118,97,108,117,101,117,13,0, + 0,0,101,120,99,95,116,114,97,99,101,98,97,99,107,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,8,0,0,0, + 95,95,101,120,105,116,95,95,149,3,0,0,115,2,0,0, + 0,0,2,117,27,0,0,0,95,73,109,112,111,114,116,76, + 111,99,107,67,111,110,116,101,120,116,46,95,95,101,120,105, + 116,95,95,78,40,6,0,0,0,117,8,0,0,0,95,95, + 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, + 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, + 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, + 95,95,117,9,0,0,0,95,95,101,110,116,101,114,95,95, + 117,8,0,0,0,95,95,101,120,105,116,95,95,40,1,0, + 0,0,117,10,0,0,0,95,95,108,111,99,97,108,115,95, + 95,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,18,0, + 0,0,95,73,109,112,111,114,116,76,111,99,107,67,111,110, + 116,101,120,116,141,3,0,0,115,6,0,0,0,16,2,6, + 2,12,4,117,18,0,0,0,95,73,109,112,111,114,116,76, + 111,99,107,67,111,110,116,101,120,116,99,3,0,0,0,0, + 0,0,0,5,0,0,0,4,0,0,0,67,0,0,0,115, + 91,0,0,0,124,1,0,106,0,0,100,1,0,124,2,0, + 100,2,0,24,131,2,0,125,3,0,116,1,0,124,3,0, + 131,1,0,124,2,0,107,0,0,114,55,0,116,2,0,100, + 3,0,131,1,0,130,1,0,110,0,0,124,3,0,100,4, + 0,25,125,4,0,124,0,0,114,87,0,100,5,0,106,3, + 0,124,4,0,124,0,0,131,2,0,83,124,4,0,83,40, + 6,0,0,0,117,50,0,0,0,82,101,115,111,108,118,101, + 32,97,32,114,101,108,97,116,105,118,101,32,109,111,100,117, + 108,101,32,110,97,109,101,32,116,111,32,97,110,32,97,98, + 115,111,108,117,116,101,32,111,110,101,46,117,1,0,0,0, + 46,105,1,0,0,0,117,50,0,0,0,97,116,116,101,109, + 112,116,101,100,32,114,101,108,97,116,105,118,101,32,105,109, + 112,111,114,116,32,98,101,121,111,110,100,32,116,111,112,45, + 108,101,118,101,108,32,112,97,99,107,97,103,101,105,0,0, + 0,0,117,7,0,0,0,123,48,125,46,123,49,125,40,4, + 0,0,0,117,6,0,0,0,114,115,112,108,105,116,117,3, + 0,0,0,108,101,110,117,10,0,0,0,86,97,108,117,101, + 69,114,114,111,114,117,6,0,0,0,102,111,114,109,97,116, + 40,5,0,0,0,117,4,0,0,0,110,97,109,101,117,7, + 0,0,0,112,97,99,107,97,103,101,117,5,0,0,0,108, + 101,118,101,108,117,4,0,0,0,98,105,116,115,117,4,0, + 0,0,98,97,115,101,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,13,0,0,0,95,114,101,115,111,108,118,101,95, + 110,97,109,101,154,3,0,0,115,10,0,0,0,0,2,22, + 1,18,1,15,1,10,1,117,13,0,0,0,95,114,101,115, + 111,108,118,101,95,110,97,109,101,99,2,0,0,0,0,0, + 0,0,5,0,0,0,4,0,0,0,67,0,0,0,115,104, + 0,0,0,116,0,0,106,1,0,116,2,0,23,125,2,0, + 120,84,0,124,2,0,68,93,72,0,125,3,0,124,3,0, + 106,3,0,124,0,0,124,1,0,131,2,0,125,4,0,124, + 4,0,100,1,0,107,9,0,114,20,0,124,0,0,116,0, + 0,106,5,0,107,7,0,114,75,0,124,4,0,83,116,0, + 0,106,5,0,124,0,0,25,106,6,0,83,113,20,0,113, + 20,0,87,100,1,0,83,100,1,0,83,40,2,0,0,0, + 117,23,0,0,0,70,105,110,100,32,97,32,109,111,100,117, + 108,101,39,115,32,108,111,97,100,101,114,46,78,40,7,0, + 0,0,117,3,0,0,0,115,121,115,117,9,0,0,0,109, + 101,116,97,95,112,97,116,104,117,19,0,0,0,95,73,77, + 80,76,73,67,73,84,95,77,69,84,65,95,80,65,84,72, + 117,11,0,0,0,102,105,110,100,95,109,111,100,117,108,101, + 117,4,0,0,0,78,111,110,101,117,7,0,0,0,109,111, + 100,117,108,101,115,117,10,0,0,0,95,95,108,111,97,100, + 101,114,95,95,40,5,0,0,0,117,4,0,0,0,110,97, + 109,101,117,4,0,0,0,112,97,116,104,117,9,0,0,0, + 109,101,116,97,95,112,97,116,104,117,6,0,0,0,102,105, + 110,100,101,114,117,6,0,0,0,108,111,97,100,101,114,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,12,0,0,0, + 95,102,105,110,100,95,109,111,100,117,108,101,163,3,0,0, + 115,16,0,0,0,0,2,13,1,13,1,18,1,12,2,15, + 1,4,2,21,2,117,12,0,0,0,95,102,105,110,100,95, + 109,111,100,117,108,101,99,3,0,0,0,0,0,0,0,4, + 0,0,0,4,0,0,0,67,0,0,0,115,194,0,0,0, + 116,0,0,124,0,0,116,1,0,131,2,0,115,45,0,116, + 2,0,100,1,0,106,3,0,116,4,0,124,0,0,131,1, + 0,131,1,0,131,1,0,130,1,0,110,0,0,124,2,0, + 100,2,0,107,0,0,114,72,0,116,5,0,100,3,0,131, + 1,0,130,1,0,110,0,0,124,1,0,114,156,0,116,0, + 0,124,1,0,116,1,0,131,2,0,115,108,0,116,2,0, + 100,4,0,131,1,0,130,1,0,113,156,0,124,1,0,116, + 6,0,106,7,0,107,7,0,114,156,0,100,5,0,125,3, + 0,116,8,0,124,3,0,106,3,0,124,1,0,131,1,0, + 131,1,0,130,1,0,113,156,0,110,0,0,124,0,0,12, + 114,190,0,124,2,0,100,2,0,107,2,0,114,190,0,116, + 5,0,100,6,0,131,1,0,130,1,0,110,0,0,100,7, + 0,83,40,8,0,0,0,117,28,0,0,0,86,101,114,105, + 102,121,32,97,114,103,117,109,101,110,116,115,32,97,114,101, + 32,34,115,97,110,101,34,46,117,31,0,0,0,109,111,100, + 117,108,101,32,110,97,109,101,32,109,117,115,116,32,98,101, + 32,115,116,114,44,32,110,111,116,32,123,125,105,0,0,0, + 0,117,18,0,0,0,108,101,118,101,108,32,109,117,115,116, + 32,98,101,32,62,61,32,48,117,31,0,0,0,95,95,112, + 97,99,107,97,103,101,95,95,32,110,111,116,32,115,101,116, + 32,116,111,32,97,32,115,116,114,105,110,103,117,62,0,0, + 0,80,97,114,101,110,116,32,109,111,100,117,108,101,32,123, + 48,33,114,125,32,110,111,116,32,108,111,97,100,101,100,44, + 32,99,97,110,110,111,116,32,112,101,114,102,111,114,109,32, + 114,101,108,97,116,105,118,101,32,105,109,112,111,114,116,117, + 17,0,0,0,69,109,112,116,121,32,109,111,100,117,108,101, + 32,110,97,109,101,78,40,9,0,0,0,117,10,0,0,0, + 105,115,105,110,115,116,97,110,99,101,117,3,0,0,0,115, + 116,114,117,9,0,0,0,84,121,112,101,69,114,114,111,114, + 117,6,0,0,0,102,111,114,109,97,116,117,4,0,0,0, + 116,121,112,101,117,10,0,0,0,86,97,108,117,101,69,114, + 114,111,114,117,3,0,0,0,115,121,115,117,7,0,0,0, + 109,111,100,117,108,101,115,117,11,0,0,0,83,121,115,116, + 101,109,69,114,114,111,114,40,4,0,0,0,117,4,0,0, + 0,110,97,109,101,117,7,0,0,0,112,97,99,107,97,103, + 101,117,5,0,0,0,108,101,118,101,108,117,3,0,0,0, + 109,115,103,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 13,0,0,0,95,115,97,110,105,116,121,95,99,104,101,99, + 107,178,3,0,0,115,24,0,0,0,0,2,15,1,30,1, + 12,1,15,1,6,1,15,1,15,1,15,1,6,2,27,1, + 19,1,117,13,0,0,0,95,115,97,110,105,116,121,95,99, + 104,101,99,107,117,20,0,0,0,78,111,32,109,111,100,117, + 108,101,32,110,97,109,101,100,32,123,33,114,125,99,2,0, + 0,0,0,0,0,0,8,0,0,0,20,0,0,0,67,0, + 0,0,115,207,1,0,0,100,9,0,125,2,0,124,0,0, + 106,1,0,100,1,0,131,1,0,100,2,0,25,125,3,0, + 124,3,0,114,175,0,124,3,0,116,2,0,106,3,0,107, + 7,0,114,59,0,124,1,0,124,3,0,131,1,0,1,110, + 0,0,124,0,0,116,2,0,106,3,0,107,6,0,114,85, + 0,116,2,0,106,3,0,124,0,0,25,83,116,2,0,106, + 3,0,124,3,0,25,125,4,0,121,13,0,124,4,0,106, + 4,0,125,2,0,87,113,175,0,4,116,5,0,107,10,0, + 114,171,0,1,1,1,116,6,0,100,3,0,23,106,7,0, + 124,0,0,124,3,0,131,2,0,125,5,0,116,8,0,124, + 5,0,100,4,0,124,0,0,131,1,1,130,1,0,89,113, + 175,0,88,110,0,0,116,9,0,124,0,0,124,2,0,131, + 2,0,125,6,0,124,6,0,100,9,0,107,8,0,114,232, + 0,116,8,0,116,6,0,106,7,0,124,0,0,131,1,0, + 100,4,0,124,0,0,131,1,1,130,1,0,110,62,0,124, + 0,0,116,2,0,106,3,0,107,6,0,114,7,1,116,2, + 0,106,3,0,124,0,0,25,125,7,0,110,31,0,124,6, + 0,106,10,0,124,0,0,131,1,0,125,7,0,116,11,0, + 100,5,0,124,0,0,124,6,0,131,3,0,1,124,3,0, + 114,89,1,116,2,0,106,3,0,124,3,0,25,125,4,0, + 116,12,0,124,4,0,124,0,0,106,1,0,100,1,0,131, + 1,0,100,6,0,25,124,7,0,131,3,0,1,110,0,0, + 116,13,0,124,7,0,100,7,0,131,2,0,12,115,120,1, + 124,7,0,106,14,0,100,9,0,107,8,0,114,203,1,121, + 59,0,124,7,0,106,15,0,124,7,0,95,14,0,116,13, + 0,124,7,0,100,8,0,131,2,0,115,178,1,124,7,0, + 106,14,0,106,1,0,100,1,0,131,1,0,100,2,0,25, + 124,7,0,95,14,0,110,0,0,87,113,203,1,4,116,5, + 0,107,10,0,114,199,1,1,1,1,89,113,203,1,88,110, + 0,0,124,7,0,83,40,10,0,0,0,117,25,0,0,0, + 70,105,110,100,32,97,110,100,32,108,111,97,100,32,116,104, + 101,32,109,111,100,117,108,101,46,117,1,0,0,0,46,105, + 0,0,0,0,117,21,0,0,0,59,32,123,125,32,105,115, + 32,110,111,116,32,97,32,112,97,99,107,97,103,101,117,4, + 0,0,0,110,97,109,101,117,18,0,0,0,105,109,112,111, + 114,116,32,123,33,114,125,32,35,32,123,33,114,125,105,2, + 0,0,0,117,11,0,0,0,95,95,112,97,99,107,97,103, + 101,95,95,117,8,0,0,0,95,95,112,97,116,104,95,95, + 78,40,16,0,0,0,117,4,0,0,0,78,111,110,101,117, + 10,0,0,0,114,112,97,114,116,105,116,105,111,110,117,3, + 0,0,0,115,121,115,117,7,0,0,0,109,111,100,117,108, + 101,115,117,8,0,0,0,95,95,112,97,116,104,95,95,117, + 14,0,0,0,65,116,116,114,105,98,117,116,101,69,114,114, + 111,114,117,8,0,0,0,95,69,82,82,95,77,83,71,117, + 6,0,0,0,102,111,114,109,97,116,117,11,0,0,0,73, + 109,112,111,114,116,69,114,114,111,114,117,12,0,0,0,95, + 102,105,110,100,95,109,111,100,117,108,101,117,11,0,0,0, + 108,111,97,100,95,109,111,100,117,108,101,117,15,0,0,0, + 118,101,114,98,111,115,101,95,109,101,115,115,97,103,101,117, + 7,0,0,0,115,101,116,97,116,116,114,117,7,0,0,0, + 104,97,115,97,116,116,114,117,11,0,0,0,95,95,112,97, + 99,107,97,103,101,95,95,117,8,0,0,0,95,95,110,97, + 109,101,95,95,40,8,0,0,0,117,4,0,0,0,110,97, + 109,101,117,7,0,0,0,105,109,112,111,114,116,95,117,4, + 0,0,0,112,97,116,104,117,6,0,0,0,112,97,114,101, + 110,116,117,13,0,0,0,112,97,114,101,110,116,95,109,111, + 100,117,108,101,117,3,0,0,0,109,115,103,117,6,0,0, + 0,108,111,97,100,101,114,117,6,0,0,0,109,111,100,117, + 108,101,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,14, + 0,0,0,95,102,105,110,100,95,97,110,100,95,108,111,97, + 100,199,3,0,0,115,62,0,0,0,0,2,6,1,19,1, + 6,1,15,1,13,2,15,1,11,2,13,1,3,1,13,1, + 13,1,22,1,26,1,15,1,12,1,30,1,15,2,16,2, + 15,1,16,1,6,2,13,1,32,2,31,1,3,1,12,1, + 15,1,32,1,13,1,8,1,117,14,0,0,0,95,102,105, + 110,100,95,97,110,100,95,108,111,97,100,105,0,0,0,0, + 99,3,0,0,0,0,0,0,0,5,0,0,0,18,0,0, + 0,67,0,0,0,115,172,0,0,0,116,0,0,124,0,0, + 124,1,0,124,2,0,131,3,0,1,124,2,0,100,1,0, + 107,4,0,114,49,0,116,1,0,124,0,0,124,1,0,124, + 2,0,131,3,0,125,0,0,110,0,0,116,2,0,131,0, + 0,143,108,0,1,121,69,0,116,3,0,106,4,0,124,0, + 0,25,125,3,0,124,3,0,100,4,0,107,8,0,114,123, + 0,100,2,0,106,6,0,124,0,0,131,1,0,125,4,0, + 116,7,0,124,4,0,100,3,0,124,0,0,131,1,1,130, + 1,0,110,0,0,124,3,0,83,87,110,18,0,4,116,8, + 0,107,10,0,114,148,0,1,1,1,89,110,1,0,88,116, + 9,0,124,0,0,116,10,0,131,2,0,83,87,100,4,0, + 81,88,100,4,0,83,40,5,0,0,0,117,50,1,0,0, + 73,109,112,111,114,116,32,97,110,100,32,114,101,116,117,114, + 110,32,116,104,101,32,109,111,100,117,108,101,32,98,97,115, + 101,100,32,111,110,32,105,116,115,32,110,97,109,101,44,32, + 116,104,101,32,112,97,99,107,97,103,101,32,116,104,101,32, + 99,97,108,108,32,105,115,10,32,32,32,32,98,101,105,110, + 103,32,109,97,100,101,32,102,114,111,109,44,32,97,110,100, + 32,116,104,101,32,108,101,118,101,108,32,97,100,106,117,115, + 116,109,101,110,116,46,10,10,32,32,32,32,84,104,105,115, + 32,102,117,110,99,116,105,111,110,32,114,101,112,114,101,115, + 101,110,116,115,32,116,104,101,32,103,114,101,97,116,101,115, + 116,32,99,111,109,109,111,110,32,100,101,110,111,109,105,110, + 97,116,111,114,32,111,102,32,102,117,110,99,116,105,111,110, + 97,108,105,116,121,10,32,32,32,32,98,101,116,119,101,101, + 110,32,105,109,112,111,114,116,95,109,111,100,117,108,101,32, + 97,110,100,32,95,95,105,109,112,111,114,116,95,95,46,32, + 84,104,105,115,32,105,110,99,108,117,100,101,115,32,115,101, + 116,116,105,110,103,32,95,95,112,97,99,107,97,103,101,95, + 95,32,105,102,10,32,32,32,32,116,104,101,32,108,111,97, + 100,101,114,32,100,105,100,32,110,111,116,46,10,10,32,32, + 32,32,105,0,0,0,0,117,40,0,0,0,105,109,112,111, + 114,116,32,111,102,32,123,125,32,104,97,108,116,101,100,59, + 32,78,111,110,101,32,105,110,32,115,121,115,46,109,111,100, + 117,108,101,115,117,4,0,0,0,110,97,109,101,78,40,11, + 0,0,0,117,13,0,0,0,95,115,97,110,105,116,121,95, + 99,104,101,99,107,117,13,0,0,0,95,114,101,115,111,108, + 118,101,95,110,97,109,101,117,18,0,0,0,95,73,109,112, + 111,114,116,76,111,99,107,67,111,110,116,101,120,116,117,3, + 0,0,0,115,121,115,117,7,0,0,0,109,111,100,117,108, + 101,115,117,4,0,0,0,78,111,110,101,117,6,0,0,0, + 102,111,114,109,97,116,117,11,0,0,0,73,109,112,111,114, + 116,69,114,114,111,114,117,8,0,0,0,75,101,121,69,114, + 114,111,114,117,14,0,0,0,95,102,105,110,100,95,97,110, + 100,95,108,111,97,100,117,11,0,0,0,95,103,99,100,95, + 105,109,112,111,114,116,40,5,0,0,0,117,4,0,0,0, + 110,97,109,101,117,7,0,0,0,112,97,99,107,97,103,101, + 117,5,0,0,0,108,101,118,101,108,117,6,0,0,0,109, + 111,100,117,108,101,117,7,0,0,0,109,101,115,115,97,103, + 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,11,0, + 0,0,95,103,99,100,95,105,109,112,111,114,116,240,3,0, + 0,115,28,0,0,0,0,9,16,1,12,1,21,1,10,1, + 3,1,13,1,12,1,6,1,9,1,21,1,8,1,13,1, + 5,1,117,11,0,0,0,95,103,99,100,95,105,109,112,111, + 114,116,99,3,0,0,0,0,0,0,0,4,0,0,0,13, + 0,0,0,3,0,0,0,115,179,0,0,0,116,0,0,136, + 0,0,100,1,0,131,2,0,114,175,0,100,2,0,124,1, + 0,107,6,0,114,86,0,116,0,0,136,0,0,100,3,0, + 131,2,0,114,86,0,116,1,0,124,1,0,131,1,0,125, + 1,0,124,1,0,106,2,0,100,2,0,131,1,0,1,124, + 1,0,106,3,0,136,0,0,106,4,0,131,1,0,1,110, + 0,0,120,86,0,135,0,0,102,1,0,100,4,0,100,5, + 0,134,0,0,124,1,0,68,131,1,0,68,93,56,0,125, + 3,0,121,29,0,124,2,0,100,6,0,106,5,0,136,0, + 0,106,6,0,124,3,0,131,2,0,131,1,0,1,87,113, + 112,0,4,116,7,0,107,10,0,114,167,0,1,1,1,89, + 113,112,0,88,113,112,0,87,110,0,0,136,0,0,83,40, + 7,0,0,0,117,238,0,0,0,70,105,103,117,114,101,32, + 111,117,116,32,119,104,97,116,32,95,95,105,109,112,111,114, + 116,95,95,32,115,104,111,117,108,100,32,114,101,116,117,114, + 110,46,10,10,32,32,32,32,84,104,101,32,105,109,112,111, + 114,116,95,32,112,97,114,97,109,101,116,101,114,32,105,115, + 32,97,32,99,97,108,108,97,98,108,101,32,119,104,105,99, + 104,32,116,97,107,101,115,32,116,104,101,32,110,97,109,101, + 32,111,102,32,109,111,100,117,108,101,32,116,111,10,32,32, + 32,32,105,109,112,111,114,116,46,32,73,116,32,105,115,32, + 114,101,113,117,105,114,101,100,32,116,111,32,100,101,99,111, + 117,112,108,101,32,116,104,101,32,102,117,110,99,116,105,111, + 110,32,102,114,111,109,32,97,115,115,117,109,105,110,103,32, + 105,109,112,111,114,116,108,105,98,39,115,10,32,32,32,32, + 105,109,112,111,114,116,32,105,109,112,108,101,109,101,110,116, + 97,116,105,111,110,32,105,115,32,100,101,115,105,114,101,100, + 46,10,10,32,32,32,32,117,8,0,0,0,95,95,112,97, + 116,104,95,95,117,1,0,0,0,42,117,7,0,0,0,95, + 95,97,108,108,95,95,99,1,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,51,0,0,0,115,36,0,0,0, + 124,0,0,93,26,0,125,1,0,116,0,0,136,0,0,124, + 1,0,131,2,0,115,3,0,124,1,0,86,1,113,3,0, + 100,0,0,83,40,1,0,0,0,78,40,1,0,0,0,117, + 7,0,0,0,104,97,115,97,116,116,114,40,2,0,0,0, + 117,2,0,0,0,46,48,117,1,0,0,0,121,40,1,0, + 0,0,117,6,0,0,0,109,111,100,117,108,101,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,9,0,0,0,60,103,101,110,101,120,112, + 114,62,24,4,0,0,115,2,0,0,0,6,0,117,35,0, + 0,0,95,104,97,110,100,108,101,95,102,114,111,109,108,105, + 115,116,46,60,108,111,99,97,108,115,62,46,60,103,101,110, + 101,120,112,114,62,117,7,0,0,0,123,48,125,46,123,49, + 125,40,8,0,0,0,117,7,0,0,0,104,97,115,97,116, + 116,114,117,4,0,0,0,108,105,115,116,117,6,0,0,0, + 114,101,109,111,118,101,117,6,0,0,0,101,120,116,101,110, + 100,117,7,0,0,0,95,95,97,108,108,95,95,117,6,0, + 0,0,102,111,114,109,97,116,117,8,0,0,0,95,95,110, + 97,109,101,95,95,117,11,0,0,0,73,109,112,111,114,116, + 69,114,114,111,114,40,4,0,0,0,117,6,0,0,0,109, + 111,100,117,108,101,117,8,0,0,0,102,114,111,109,108,105, + 115,116,117,7,0,0,0,105,109,112,111,114,116,95,117,1, + 0,0,0,120,40,0,0,0,0,40,1,0,0,0,117,6, + 0,0,0,109,111,100,117,108,101,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,16,0,0,0, + 95,104,97,110,100,108,101,95,102,114,111,109,108,105,115,116, + 9,4,0,0,115,22,0,0,0,0,10,15,1,27,1,12, + 1,13,1,19,1,32,1,3,1,29,1,13,1,12,1,117, + 16,0,0,0,95,104,97,110,100,108,101,95,102,114,111,109, + 108,105,115,116,99,1,0,0,0,0,0,0,0,2,0,0, + 0,2,0,0,0,67,0,0,0,115,78,0,0,0,124,0, + 0,106,0,0,100,1,0,131,1,0,125,1,0,124,1,0, + 100,6,0,107,8,0,114,74,0,124,0,0,100,2,0,25, + 125,1,0,100,3,0,124,0,0,107,7,0,114,74,0,124, + 1,0,106,2,0,100,4,0,131,1,0,100,5,0,25,125, + 1,0,113,74,0,110,0,0,124,1,0,83,40,7,0,0, + 0,117,167,0,0,0,67,97,108,99,117,108,97,116,101,32, + 119,104,97,116,32,95,95,112,97,99,107,97,103,101,95,95, + 32,115,104,111,117,108,100,32,98,101,46,10,10,32,32,32, + 32,95,95,112,97,99,107,97,103,101,95,95,32,105,115,32, + 110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116, + 111,32,98,101,32,100,101,102,105,110,101,100,32,111,114,32, + 99,111,117,108,100,32,98,101,32,115,101,116,32,116,111,32, + 78,111,110,101,10,32,32,32,32,116,111,32,114,101,112,114, + 101,115,101,110,116,32,116,104,97,116,32,105,116,115,32,112, + 114,111,112,101,114,32,118,97,108,117,101,32,105,115,32,117, + 110,107,110,111,119,110,46,10,10,32,32,32,32,117,11,0, + 0,0,95,95,112,97,99,107,97,103,101,95,95,117,8,0, + 0,0,95,95,110,97,109,101,95,95,117,8,0,0,0,95, + 95,112,97,116,104,95,95,117,1,0,0,0,46,105,0,0, + 0,0,78,40,3,0,0,0,117,3,0,0,0,103,101,116, + 117,4,0,0,0,78,111,110,101,117,10,0,0,0,114,112, + 97,114,116,105,116,105,111,110,40,2,0,0,0,117,7,0, + 0,0,103,108,111,98,97,108,115,117,7,0,0,0,112,97, + 99,107,97,103,101,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,17,0,0,0,95,99,97,108,99,95,95,95,112,97, + 99,107,97,103,101,95,95,32,4,0,0,115,12,0,0,0, + 0,7,15,1,12,1,10,1,12,1,25,1,117,17,0,0, + 0,95,99,97,108,99,95,95,95,112,97,99,107,97,103,101, + 95,95,99,5,0,0,0,0,0,0,0,9,0,0,0,5, + 0,0,0,67,0,0,0,115,235,0,0,0,124,4,0,100, + 1,0,107,2,0,114,27,0,116,0,0,124,0,0,131,1, + 0,125,5,0,110,30,0,116,1,0,124,1,0,131,1,0, + 125,6,0,116,0,0,124,0,0,124,6,0,124,4,0,131, + 3,0,125,5,0,124,3,0,115,215,0,124,4,0,100,1, + 0,107,2,0,114,130,0,124,0,0,106,2,0,100,2,0, + 131,1,0,125,7,0,124,7,0,100,5,0,107,2,0,114, + 106,0,124,5,0,83,116,3,0,106,4,0,124,0,0,100, + 4,0,124,7,0,133,2,0,25,25,83,113,231,0,124,0, + 0,115,140,0,124,5,0,83,116,5,0,124,0,0,131,1, + 0,116,5,0,124,0,0,106,6,0,100,2,0,131,1,0, + 100,1,0,25,131,1,0,24,125,8,0,116,3,0,106,4, + 0,124,5,0,106,7,0,100,4,0,116,5,0,124,5,0, + 106,7,0,131,1,0,124,8,0,24,133,2,0,25,25,83, + 110,16,0,116,8,0,124,5,0,124,3,0,116,0,0,131, + 3,0,83,100,4,0,83,40,6,0,0,0,117,214,1,0, + 0,73,109,112,111,114,116,32,97,32,109,111,100,117,108,101, + 46,10,10,32,32,32,32,84,104,101,32,39,103,108,111,98, + 97,108,115,39,32,97,114,103,117,109,101,110,116,32,105,115, + 32,117,115,101,100,32,116,111,32,105,110,102,101,114,32,119, + 104,101,114,101,32,116,104,101,32,105,109,112,111,114,116,32, + 105,115,32,111,99,99,117,114,105,110,103,32,102,114,111,109, + 10,32,32,32,32,116,111,32,104,97,110,100,108,101,32,114, + 101,108,97,116,105,118,101,32,105,109,112,111,114,116,115,46, + 32,84,104,101,32,39,108,111,99,97,108,115,39,32,97,114, + 103,117,109,101,110,116,32,105,115,32,105,103,110,111,114,101, + 100,46,32,84,104,101,10,32,32,32,32,39,102,114,111,109, + 108,105,115,116,39,32,97,114,103,117,109,101,110,116,32,115, + 112,101,99,105,102,105,101,115,32,119,104,97,116,32,115,104, + 111,117,108,100,32,101,120,105,115,116,32,97,115,32,97,116, + 116,114,105,98,117,116,101,115,32,111,110,32,116,104,101,32, + 109,111,100,117,108,101,10,32,32,32,32,98,101,105,110,103, + 32,105,109,112,111,114,116,101,100,32,40,101,46,103,46,32, + 96,96,102,114,111,109,32,109,111,100,117,108,101,32,105,109, + 112,111,114,116,32,60,102,114,111,109,108,105,115,116,62,96, + 96,41,46,32,32,84,104,101,32,39,108,101,118,101,108,39, + 10,32,32,32,32,97,114,103,117,109,101,110,116,32,114,101, + 112,114,101,115,101,110,116,115,32,116,104,101,32,112,97,99, + 107,97,103,101,32,108,111,99,97,116,105,111,110,32,116,111, + 32,105,109,112,111,114,116,32,102,114,111,109,32,105,110,32, + 97,32,114,101,108,97,116,105,118,101,10,32,32,32,32,105, + 109,112,111,114,116,32,40,101,46,103,46,32,96,96,102,114, + 111,109,32,46,46,112,107,103,32,105,109,112,111,114,116,32, + 109,111,100,96,96,32,119,111,117,108,100,32,104,97,118,101, + 32,97,32,39,108,101,118,101,108,39,32,111,102,32,50,41, + 46,10,10,32,32,32,32,105,0,0,0,0,117,1,0,0, + 0,46,105,1,0,0,0,78,105,255,255,255,255,40,9,0, + 0,0,117,11,0,0,0,95,103,99,100,95,105,109,112,111, + 114,116,117,17,0,0,0,95,99,97,108,99,95,95,95,112, + 97,99,107,97,103,101,95,95,117,4,0,0,0,102,105,110, + 100,117,3,0,0,0,115,121,115,117,7,0,0,0,109,111, + 100,117,108,101,115,117,3,0,0,0,108,101,110,117,9,0, + 0,0,112,97,114,116,105,116,105,111,110,117,8,0,0,0, + 95,95,110,97,109,101,95,95,117,16,0,0,0,95,104,97, + 110,100,108,101,95,102,114,111,109,108,105,115,116,40,9,0, + 0,0,117,4,0,0,0,110,97,109,101,117,7,0,0,0, + 103,108,111,98,97,108,115,117,6,0,0,0,108,111,99,97, + 108,115,117,8,0,0,0,102,114,111,109,108,105,115,116,117, + 5,0,0,0,108,101,118,101,108,117,6,0,0,0,109,111, + 100,117,108,101,117,7,0,0,0,112,97,99,107,97,103,101, + 117,5,0,0,0,105,110,100,101,120,117,7,0,0,0,99, + 117,116,95,111,102,102,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,10,0,0,0,95,95,105,109,112,111,114,116,95, + 95,47,4,0,0,115,30,0,0,0,0,11,12,1,15,2, + 12,1,18,1,6,3,12,1,15,1,12,1,4,2,24,1, + 6,1,4,2,35,1,40,2,117,10,0,0,0,95,95,105, + 109,112,111,114,116,95,95,99,2,0,0,0,0,0,0,0, + 9,0,0,0,12,0,0,0,67,0,0,0,115,109,1,0, + 0,124,1,0,97,0,0,124,0,0,97,1,0,120,47,0, + 116,0,0,116,1,0,102,2,0,68,93,33,0,125,2,0, + 116,2,0,124,2,0,100,1,0,131,2,0,115,25,0,116, + 3,0,124,2,0,95,4,0,113,25,0,113,25,0,87,116, + 1,0,106,5,0,116,6,0,25,125,3,0,120,76,0,100, + 17,0,68,93,68,0,125,4,0,124,4,0,116,1,0,106, + 5,0,107,7,0,114,121,0,116,3,0,106,7,0,124,4, + 0,131,1,0,125,5,0,110,13,0,116,1,0,106,5,0, + 124,4,0,25,125,5,0,116,8,0,124,3,0,124,4,0, + 124,5,0,131,3,0,1,113,82,0,87,120,153,0,100,18, + 0,100,19,0,100,20,0,103,3,0,68,93,124,0,92,2, + 0,125,6,0,125,7,0,124,6,0,116,1,0,106,5,0, + 107,6,0,114,214,0,116,1,0,106,5,0,124,6,0,25, + 125,8,0,80,113,170,0,121,56,0,116,3,0,106,7,0, + 124,6,0,131,1,0,125,8,0,124,6,0,100,10,0,107, + 2,0,114,12,1,100,11,0,116,1,0,106,9,0,107,6, + 0,114,12,1,100,7,0,125,7,0,110,0,0,80,87,113, + 170,0,4,116,10,0,107,10,0,114,37,1,1,1,1,119, + 170,0,89,113,170,0,88,113,170,0,87,116,10,0,100,12, + 0,131,1,0,130,1,0,116,8,0,124,3,0,100,13,0, + 124,8,0,131,3,0,1,116,8,0,124,3,0,100,14,0, + 124,7,0,131,3,0,1,116,8,0,124,3,0,100,15,0, + 116,11,0,131,0,0,131,3,0,1,100,16,0,83,40,21, + 0,0,0,117,250,0,0,0,83,101,116,117,112,32,105,109, + 112,111,114,116,108,105,98,32,98,121,32,105,109,112,111,114, + 116,105,110,103,32,110,101,101,100,101,100,32,98,117,105,108, + 116,45,105,110,32,109,111,100,117,108,101,115,32,97,110,100, + 32,105,110,106,101,99,116,105,110,103,32,116,104,101,109,10, + 32,32,32,32,105,110,116,111,32,116,104,101,32,103,108,111, + 98,97,108,32,110,97,109,101,115,112,97,99,101,46,10,10, + 32,32,32,32,65,115,32,115,121,115,32,105,115,32,110,101, + 101,100,101,100,32,102,111,114,32,115,121,115,46,109,111,100, + 117,108,101,115,32,97,99,99,101,115,115,32,97,110,100,32, + 95,105,109,112,32,105,115,32,110,101,101,100,101,100,32,116, + 111,32,108,111,97,100,32,98,117,105,108,116,45,105,110,10, + 32,32,32,32,109,111,100,117,108,101,115,44,32,116,104,111, + 115,101,32,116,119,111,32,109,111,100,117,108,101,115,32,109, + 117,115,116,32,98,101,32,101,120,112,108,105,99,105,116,108, + 121,32,112,97,115,115,101,100,32,105,110,46,10,10,32,32, + 32,32,117,10,0,0,0,95,95,108,111,97,100,101,114,95, + 95,117,3,0,0,0,95,105,111,117,9,0,0,0,95,119, + 97,114,110,105,110,103,115,117,8,0,0,0,98,117,105,108, + 116,105,110,115,117,7,0,0,0,109,97,114,115,104,97,108, + 117,5,0,0,0,112,111,115,105,120,117,1,0,0,0,47, + 117,2,0,0,0,110,116,117,1,0,0,0,92,117,3,0, + 0,0,111,115,50,117,7,0,0,0,69,77,88,32,71,67, + 67,117,30,0,0,0,105,109,112,111,114,116,108,105,98,32, + 114,101,113,117,105,114,101,115,32,112,111,115,105,120,32,111, + 114,32,110,116,117,3,0,0,0,95,111,115,117,8,0,0, + 0,112,97,116,104,95,115,101,112,117,11,0,0,0,95,114, + 101,108,97,120,95,99,97,115,101,78,40,4,0,0,0,117, + 3,0,0,0,95,105,111,117,9,0,0,0,95,119,97,114, + 110,105,110,103,115,117,8,0,0,0,98,117,105,108,116,105, + 110,115,117,7,0,0,0,109,97,114,115,104,97,108,40,2, + 0,0,0,117,5,0,0,0,112,111,115,105,120,117,1,0, + 0,0,47,40,2,0,0,0,117,2,0,0,0,110,116,117, + 1,0,0,0,92,40,2,0,0,0,117,3,0,0,0,111, + 115,50,117,1,0,0,0,92,40,12,0,0,0,117,4,0, + 0,0,95,105,109,112,117,3,0,0,0,115,121,115,117,7, + 0,0,0,104,97,115,97,116,116,114,117,15,0,0,0,66, + 117,105,108,116,105,110,73,109,112,111,114,116,101,114,117,10, + 0,0,0,95,95,108,111,97,100,101,114,95,95,117,7,0, + 0,0,109,111,100,117,108,101,115,117,8,0,0,0,95,95, + 110,97,109,101,95,95,117,11,0,0,0,108,111,97,100,95, + 109,111,100,117,108,101,117,7,0,0,0,115,101,116,97,116, + 116,114,117,7,0,0,0,118,101,114,115,105,111,110,117,11, + 0,0,0,73,109,112,111,114,116,69,114,114,111,114,117,16, + 0,0,0,95,109,97,107,101,95,114,101,108,97,120,95,99, + 97,115,101,40,9,0,0,0,117,10,0,0,0,115,121,115, + 95,109,111,100,117,108,101,117,11,0,0,0,95,105,109,112, + 95,109,111,100,117,108,101,117,6,0,0,0,109,111,100,117, + 108,101,117,11,0,0,0,115,101,108,102,95,109,111,100,117, + 108,101,117,12,0,0,0,98,117,105,108,116,105,110,95,110, + 97,109,101,117,14,0,0,0,98,117,105,108,116,105,110,95, + 109,111,100,117,108,101,117,10,0,0,0,98,117,105,108,116, + 105,110,95,111,115,117,8,0,0,0,112,97,116,104,95,115, + 101,112,117,9,0,0,0,111,115,95,109,111,100,117,108,101, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,6,0,0, + 0,95,115,101,116,117,112,81,4,0,0,115,52,0,0,0, + 0,9,6,1,6,2,19,1,15,1,16,2,13,1,13,1, + 15,1,18,2,13,1,20,2,28,1,15,1,13,1,4,2, + 3,1,15,2,27,1,9,1,5,1,13,1,12,2,12,1, + 16,1,16,2,117,6,0,0,0,95,115,101,116,117,112,99, + 2,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, + 67,0,0,0,115,44,0,0,0,116,0,0,124,0,0,124, + 1,0,131,2,0,1,116,1,0,106,2,0,125,2,0,116, + 2,0,116,1,0,95,2,0,124,2,0,116,1,0,95,3, + 0,100,1,0,83,40,2,0,0,0,117,202,0,0,0,73, + 110,115,116,97,108,108,32,105,109,112,111,114,116,108,105,98, + 32,97,115,32,116,104,101,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,111,102,32,105,109,112,111,114,116, + 46,10,10,32,32,32,32,73,116,32,105,115,32,97,115,115, + 117,109,101,100,32,116,104,97,116,32,95,105,109,112,32,97, + 110,100,32,115,121,115,32,104,97,118,101,32,98,101,101,110, + 32,105,109,112,111,114,116,101,100,32,97,110,100,32,105,110, + 106,101,99,116,101,100,32,105,110,116,111,32,116,104,101,10, + 32,32,32,32,103,108,111,98,97,108,32,110,97,109,101,115, + 112,97,99,101,32,102,111,114,32,116,104,101,32,109,111,100, + 117,108,101,32,112,114,105,111,114,32,116,111,32,99,97,108, + 108,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105, + 111,110,46,10,10,32,32,32,32,78,40,4,0,0,0,117, + 6,0,0,0,95,115,101,116,117,112,117,8,0,0,0,98, + 117,105,108,116,105,110,115,117,10,0,0,0,95,95,105,109, + 112,111,114,116,95,95,117,19,0,0,0,95,95,111,114,105, + 103,105,110,97,108,95,105,109,112,111,114,116,95,95,40,3, + 0,0,0,117,10,0,0,0,115,121,115,95,109,111,100,117, + 108,101,117,11,0,0,0,95,105,109,112,95,109,111,100,117, + 108,101,117,11,0,0,0,111,114,105,103,95,105,109,112,111, + 114,116,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,8, + 0,0,0,95,105,110,115,116,97,108,108,126,4,0,0,115, + 8,0,0,0,0,7,13,1,9,1,9,1,117,8,0,0, + 0,95,105,110,115,116,97,108,108,78,40,3,0,0,0,117, + 3,0,0,0,119,105,110,117,6,0,0,0,99,121,103,119, + 105,110,117,6,0,0,0,100,97,114,119,105,110,40,56,0, + 0,0,117,7,0,0,0,95,95,100,111,99,95,95,117,26, + 0,0,0,67,65,83,69,95,73,78,83,69,78,83,73,84, + 73,86,69,95,80,76,65,84,70,79,82,77,83,117,16,0, + 0,0,95,109,97,107,101,95,114,101,108,97,120,95,99,97, + 115,101,117,7,0,0,0,95,119,95,108,111,110,103,117,7, + 0,0,0,95,114,95,108,111,110,103,117,10,0,0,0,95, + 112,97,116,104,95,106,111,105,110,117,12,0,0,0,95,112, + 97,116,104,95,101,120,105,115,116,115,117,18,0,0,0,95, + 112,97,116,104,95,105,115,95,109,111,100,101,95,116,121,112, + 101,117,12,0,0,0,95,112,97,116,104,95,105,115,102,105, + 108,101,117,11,0,0,0,95,112,97,116,104,95,105,115,100, + 105,114,117,17,0,0,0,95,112,97,116,104,95,119,105,116, + 104,111,117,116,95,101,120,116,117,14,0,0,0,95,112,97, + 116,104,95,97,98,115,111,108,117,116,101,117,13,0,0,0, + 95,119,114,105,116,101,95,97,116,111,109,105,99,117,5,0, + 0,0,95,119,114,97,112,117,4,0,0,0,116,121,112,101, + 117,8,0,0,0,95,95,99,111,100,101,95,95,117,9,0, + 0,0,99,111,100,101,95,116,121,112,101,117,10,0,0,0, + 110,101,119,95,109,111,100,117,108,101,117,15,0,0,0,118, + 101,114,98,111,115,101,95,109,101,115,115,97,103,101,117,11, + 0,0,0,115,101,116,95,112,97,99,107,97,103,101,117,10, + 0,0,0,115,101,116,95,108,111,97,100,101,114,117,17,0, + 0,0,109,111,100,117,108,101,95,102,111,114,95,108,111,97, + 100,101,114,117,11,0,0,0,95,99,104,101,99,107,95,110, + 97,109,101,117,17,0,0,0,95,114,101,113,117,105,114,101, + 115,95,98,117,105,108,116,105,110,117,16,0,0,0,95,114, + 101,113,117,105,114,101,115,95,102,114,111,122,101,110,117,12, + 0,0,0,95,115,117,102,102,105,120,95,108,105,115,116,117, + 15,0,0,0,66,117,105,108,116,105,110,73,109,112,111,114, + 116,101,114,117,14,0,0,0,70,114,111,122,101,110,73,109, + 112,111,114,116,101,114,117,13,0,0,0,95,76,111,97,100, + 101,114,66,97,115,105,99,115,117,12,0,0,0,83,111,117, + 114,99,101,76,111,97,100,101,114,117,11,0,0,0,95,70, + 105,108,101,76,111,97,100,101,114,117,17,0,0,0,95,83, + 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,117, + 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, + 105,108,101,76,111,97,100,101,114,117,20,0,0,0,95,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,117,10,0,0,0,80,97,116,104,70,105,110,100,101, + 114,117,11,0,0,0,95,70,105,108,101,70,105,110,100,101, + 114,117,20,0,0,0,95,83,111,117,114,99,101,70,105,110, + 100,101,114,68,101,116,97,105,108,115,117,24,0,0,0,95, + 83,111,117,114,99,101,108,101,115,115,70,105,110,100,101,114, + 68,101,116,97,105,108,115,117,23,0,0,0,95,69,120,116, + 101,110,115,105,111,110,70,105,110,100,101,114,68,101,116,97, + 105,108,115,117,15,0,0,0,95,102,105,108,101,95,112,97, + 116,104,95,104,111,111,107,117,18,0,0,0,95,68,69,70, + 65,85,76,84,95,80,65,84,72,95,72,79,79,75,117,18, + 0,0,0,95,68,101,102,97,117,108,116,80,97,116,104,70, + 105,110,100,101,114,117,18,0,0,0,95,73,109,112,111,114, + 116,76,111,99,107,67,111,110,116,101,120,116,117,13,0,0, + 0,95,114,101,115,111,108,118,101,95,110,97,109,101,117,12, + 0,0,0,95,102,105,110,100,95,109,111,100,117,108,101,117, + 13,0,0,0,95,115,97,110,105,116,121,95,99,104,101,99, + 107,117,19,0,0,0,95,73,77,80,76,73,67,73,84,95, + 77,69,84,65,95,80,65,84,72,117,8,0,0,0,95,69, + 82,82,95,77,83,71,117,14,0,0,0,95,102,105,110,100, + 95,97,110,100,95,108,111,97,100,117,4,0,0,0,78,111, + 110,101,117,11,0,0,0,95,103,99,100,95,105,109,112,111, + 114,116,117,16,0,0,0,95,104,97,110,100,108,101,95,102, + 114,111,109,108,105,115,116,117,17,0,0,0,95,99,97,108, + 99,95,95,95,112,97,99,107,97,103,101,95,95,117,10,0, + 0,0,95,95,105,109,112,111,114,116,95,95,117,6,0,0, + 0,95,115,101,116,117,112,117,8,0,0,0,95,105,110,115, + 116,97,108,108,40,0,0,0,0,40,0,0,0,0,40,0, 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,20,0,0,0,95,83,111,117,114,99, - 101,70,105,110,100,101,114,68,101,116,97,105,108,115,70,3, - 0,0,115,6,0,0,0,16,2,6,1,6,2,117,20,0, - 0,0,95,83,111,117,114,99,101,70,105,110,100,101,114,68, - 101,116,97,105,108,115,99,1,0,0,0,0,0,0,0,1, - 0,0,0,2,0,0,0,66,0,0,0,115,44,0,0,0, - 124,0,0,69,101,0,0,90,1,0,100,0,0,90,2,0, - 101,3,0,90,4,0,100,4,0,90,6,0,100,1,0,100, - 2,0,132,0,0,90,7,0,100,3,0,83,40,5,0,0, - 0,117,24,0,0,0,95,83,111,117,114,99,101,108,101,115, - 115,70,105,110,100,101,114,68,101,116,97,105,108,115,99,1, - 0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,67, - 0,0,0,115,22,0,0,0,116,0,0,116,1,0,106,2, - 0,131,1,0,124,0,0,95,3,0,100,0,0,83,40,1, - 0,0,0,78,40,4,0,0,0,117,12,0,0,0,95,115, - 117,102,102,105,120,95,108,105,115,116,117,3,0,0,0,105, - 109,112,117,11,0,0,0,80,89,95,67,79,77,80,73,76, - 69,68,117,8,0,0,0,115,117,102,102,105,120,101,115,40, - 1,0,0,0,117,4,0,0,0,115,101,108,102,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,8,0,0,0,95,95, - 105,110,105,116,95,95,83,3,0,0,115,2,0,0,0,0, - 1,117,33,0,0,0,95,83,111,117,114,99,101,108,101,115, - 115,70,105,110,100,101,114,68,101,116,97,105,108,115,46,95, - 95,105,110,105,116,95,95,78,84,40,8,0,0,0,117,8, - 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, - 95,95,109,111,100,117,108,101,95,95,117,12,0,0,0,95, - 95,113,117,97,108,110,97,109,101,95,95,117,21,0,0,0, - 95,83,111,117,114,99,101,108,101,115,115,70,105,108,101,76, - 111,97,100,101,114,117,6,0,0,0,108,111,97,100,101,114, - 117,4,0,0,0,84,114,117,101,117,17,0,0,0,115,117, - 112,112,111,114,116,115,95,112,97,99,107,97,103,101,115,117, - 8,0,0,0,95,95,105,110,105,116,95,95,40,1,0,0, - 0,117,10,0,0,0,95,95,108,111,99,97,108,115,95,95, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,24,0,0, - 0,95,83,111,117,114,99,101,108,101,115,115,70,105,110,100, - 101,114,68,101,116,97,105,108,115,78,3,0,0,115,6,0, - 0,0,16,2,6,1,6,2,117,24,0,0,0,95,83,111, - 117,114,99,101,108,101,115,115,70,105,110,100,101,114,68,101, - 116,97,105,108,115,99,1,0,0,0,0,0,0,0,1,0, - 0,0,2,0,0,0,66,0,0,0,115,44,0,0,0,124, - 0,0,69,101,0,0,90,1,0,100,0,0,90,2,0,101, - 3,0,90,4,0,100,4,0,90,6,0,100,1,0,100,2, - 0,132,0,0,90,7,0,100,3,0,83,40,5,0,0,0, - 117,23,0,0,0,95,69,120,116,101,110,115,105,111,110,70, - 105,110,100,101,114,68,101,116,97,105,108,115,99,1,0,0, - 0,0,0,0,0,1,0,0,0,2,0,0,0,67,0,0, - 0,115,22,0,0,0,116,0,0,116,1,0,106,2,0,131, - 1,0,124,0,0,95,3,0,100,0,0,83,40,1,0,0, - 0,78,40,4,0,0,0,117,12,0,0,0,95,115,117,102, - 102,105,120,95,108,105,115,116,117,3,0,0,0,105,109,112, - 117,11,0,0,0,67,95,69,88,84,69,78,83,73,79,78, - 117,8,0,0,0,115,117,102,102,105,120,101,115,40,1,0, - 0,0,117,4,0,0,0,115,101,108,102,40,0,0,0,0, - 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, - 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, - 116,115,116,114,97,112,62,117,8,0,0,0,95,95,105,110, - 105,116,95,95,92,3,0,0,115,2,0,0,0,0,1,117, - 32,0,0,0,95,69,120,116,101,110,115,105,111,110,70,105, - 110,100,101,114,68,101,116,97,105,108,115,46,95,95,105,110, - 105,116,95,95,78,70,40,8,0,0,0,117,8,0,0,0, - 95,95,110,97,109,101,95,95,117,10,0,0,0,95,95,109, - 111,100,117,108,101,95,95,117,12,0,0,0,95,95,113,117, - 97,108,110,97,109,101,95,95,117,20,0,0,0,95,69,120, - 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, - 114,117,6,0,0,0,108,111,97,100,101,114,117,5,0,0, - 0,70,97,108,115,101,117,17,0,0,0,115,117,112,112,111, - 114,116,115,95,112,97,99,107,97,103,101,115,117,8,0,0, - 0,95,95,105,110,105,116,95,95,40,1,0,0,0,117,10, - 0,0,0,95,95,108,111,99,97,108,115,95,95,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,23,0,0,0,95,69, - 120,116,101,110,115,105,111,110,70,105,110,100,101,114,68,101, - 116,97,105,108,115,87,3,0,0,115,6,0,0,0,16,2, - 6,1,6,2,117,23,0,0,0,95,69,120,116,101,110,115, - 105,111,110,70,105,110,100,101,114,68,101,116,97,105,108,115, - 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, - 0,67,0,0,0,115,62,0,0,0,116,0,0,124,0,0, - 131,1,0,114,40,0,116,1,0,124,0,0,116,2,0,131, - 0,0,116,3,0,131,0,0,116,4,0,131,0,0,131,4, - 0,83,116,5,0,100,1,0,100,2,0,124,0,0,131,1, - 1,130,1,0,100,3,0,83,40,4,0,0,0,117,55,0, - 0,0,73,102,32,116,104,101,32,112,97,116,104,32,105,115, - 32,97,32,100,105,114,101,99,116,111,114,121,44,32,114,101, - 116,117,114,110,32,97,32,102,105,108,101,45,98,97,115,101, - 100,32,102,105,110,100,101,114,46,117,30,0,0,0,111,110, - 108,121,32,100,105,114,101,99,116,111,114,105,101,115,32,97, - 114,101,32,115,117,112,112,111,114,116,101,100,117,4,0,0, - 0,112,97,116,104,78,40,6,0,0,0,117,11,0,0,0, - 95,112,97,116,104,95,105,115,100,105,114,117,11,0,0,0, - 95,70,105,108,101,70,105,110,100,101,114,117,23,0,0,0, - 95,69,120,116,101,110,115,105,111,110,70,105,110,100,101,114, - 68,101,116,97,105,108,115,117,20,0,0,0,95,83,111,117, - 114,99,101,70,105,110,100,101,114,68,101,116,97,105,108,115, - 117,24,0,0,0,95,83,111,117,114,99,101,108,101,115,115, - 70,105,110,100,101,114,68,101,116,97,105,108,115,117,11,0, - 0,0,73,109,112,111,114,116,69,114,114,111,114,40,1,0, - 0,0,117,4,0,0,0,112,97,116,104,40,0,0,0,0, - 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, - 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, - 116,115,116,114,97,112,62,117,15,0,0,0,95,102,105,108, - 101,95,112,97,116,104,95,104,111,111,107,98,3,0,0,115, - 10,0,0,0,0,2,12,1,12,1,6,1,10,2,117,15, - 0,0,0,95,102,105,108,101,95,112,97,116,104,95,104,111, - 111,107,99,1,0,0,0,0,0,0,0,1,0,0,0,4, - 0,0,0,2,0,0,0,115,74,0,0,0,124,0,0,69, - 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, - 3,0,101,4,0,135,0,0,102,1,0,100,2,0,100,3, - 0,134,0,0,131,1,0,90,5,0,101,4,0,135,0,0, - 102,1,0,100,4,0,100,5,0,134,0,0,131,1,0,90, - 6,0,135,0,0,83,40,6,0,0,0,117,18,0,0,0, - 95,68,101,102,97,117,108,116,80,97,116,104,70,105,110,100, - 101,114,117,77,0,0,0,83,117,98,99,108,97,115,115,32, - 111,102,32,80,97,116,104,70,105,110,100,101,114,32,116,104, - 97,116,32,105,109,112,108,101,109,101,110,116,115,32,105,109, - 112,108,105,99,105,116,32,115,101,109,97,110,116,105,99,115, - 32,102,111,114,10,32,32,32,32,95,95,105,109,112,111,114, - 116,95,95,46,99,2,0,0,0,0,0,0,0,3,0,0, - 0,11,0,0,0,3,0,0,0,115,79,0,0,0,121,20, - 0,116,0,0,131,0,0,106,1,0,124,1,0,131,1,0, - 83,87,110,52,0,4,116,2,0,107,10,0,114,74,0,1, - 1,1,116,3,0,116,4,0,106,5,0,103,2,0,125,2, - 0,116,0,0,131,0,0,106,1,0,124,1,0,124,2,0, - 131,2,0,83,89,110,1,0,88,100,1,0,83,40,2,0, - 0,0,117,53,0,0,0,83,101,97,114,99,104,32,115,121, - 115,46,112,97,116,104,95,104,111,111,107,115,32,97,115,32, - 119,101,108,108,32,97,115,32,105,109,112,108,105,99,105,116, - 32,112,97,116,104,32,104,111,111,107,115,46,78,40,6,0, - 0,0,117,5,0,0,0,115,117,112,101,114,117,11,0,0, - 0,95,112,97,116,104,95,104,111,111,107,115,117,11,0,0, - 0,73,109,112,111,114,116,69,114,114,111,114,117,18,0,0, - 0,95,68,69,70,65,85,76,84,95,80,65,84,72,95,72, - 79,79,75,117,3,0,0,0,105,109,112,117,12,0,0,0, - 78,117,108,108,73,109,112,111,114,116,101,114,40,3,0,0, - 0,117,3,0,0,0,99,108,115,117,4,0,0,0,112,97, - 116,104,117,14,0,0,0,105,109,112,108,105,99,105,116,95, - 104,111,111,107,115,40,1,0,0,0,117,10,0,0,0,64, - 95,95,99,108,97,115,115,95,95,40,0,0,0,0,117,29, - 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,11,0,0,0,95,112,97,116,104,95,104,111,111,107,115, - 115,3,0,0,115,10,0,0,0,0,3,3,1,20,1,13, - 1,15,1,117,30,0,0,0,95,68,101,102,97,117,108,116, - 80,97,116,104,70,105,110,100,101,114,46,95,112,97,116,104, - 95,104,111,111,107,115,99,2,0,0,0,0,0,0,0,2, - 0,0,0,3,0,0,0,3,0,0,0,115,19,0,0,0, - 116,0,0,131,0,0,106,1,0,124,1,0,116,2,0,131, - 2,0,83,40,1,0,0,0,117,81,0,0,0,85,115,101, - 32,116,104,101,32,100,101,102,97,117,108,116,32,112,97,116, - 104,32,104,111,111,107,32,119,104,101,110,32,78,111,110,101, - 32,105,115,32,115,116,111,114,101,100,32,105,110,10,32,32, - 32,32,32,32,32,32,115,121,115,46,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,46,40,3, - 0,0,0,117,5,0,0,0,115,117,112,101,114,117,20,0, - 0,0,95,112,97,116,104,95,105,109,112,111,114,116,101,114, - 95,99,97,99,104,101,117,18,0,0,0,95,68,69,70,65, - 85,76,84,95,80,65,84,72,95,72,79,79,75,40,2,0, - 0,0,117,3,0,0,0,99,108,115,117,4,0,0,0,112, - 97,116,104,40,1,0,0,0,117,10,0,0,0,64,95,95, - 99,108,97,115,115,95,95,40,0,0,0,0,117,29,0,0, - 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,20, - 0,0,0,95,112,97,116,104,95,105,109,112,111,114,116,101, - 114,95,99,97,99,104,101,124,3,0,0,115,2,0,0,0, - 0,4,117,39,0,0,0,95,68,101,102,97,117,108,116,80, - 97,116,104,70,105,110,100,101,114,46,95,112,97,116,104,95, - 105,109,112,111,114,116,101,114,95,99,97,99,104,101,40,7, - 0,0,0,117,8,0,0,0,95,95,110,97,109,101,95,95, - 117,10,0,0,0,95,95,109,111,100,117,108,101,95,95,117, - 12,0,0,0,95,95,113,117,97,108,110,97,109,101,95,95, - 117,7,0,0,0,95,95,100,111,99,95,95,117,11,0,0, - 0,99,108,97,115,115,109,101,116,104,111,100,117,11,0,0, - 0,95,112,97,116,104,95,104,111,111,107,115,117,20,0,0, - 0,95,112,97,116,104,95,105,109,112,111,114,116,101,114,95, - 99,97,99,104,101,40,1,0,0,0,117,10,0,0,0,95, - 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,1, - 0,0,0,117,10,0,0,0,64,95,95,99,108,97,115,115, - 95,95,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,18,0,0,0,95,68,101,102,97,117,108, - 116,80,97,116,104,70,105,110,100,101,114,110,3,0,0,115, - 6,0,0,0,16,3,6,2,24,9,117,18,0,0,0,95, - 68,101,102,97,117,108,116,80,97,116,104,70,105,110,100,101, - 114,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, - 0,0,66,0,0,0,115,50,0,0,0,124,0,0,69,101, - 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, - 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, - 100,5,0,132,0,0,90,5,0,100,6,0,83,40,7,0, - 0,0,117,18,0,0,0,95,73,109,112,111,114,116,76,111, - 99,107,67,111,110,116,101,120,116,117,36,0,0,0,67,111, - 110,116,101,120,116,32,109,97,110,97,103,101,114,32,102,111, - 114,32,116,104,101,32,105,109,112,111,114,116,32,108,111,99, - 107,46,99,1,0,0,0,0,0,0,0,1,0,0,0,1, - 0,0,0,67,0,0,0,115,14,0,0,0,116,0,0,106, - 1,0,131,0,0,1,100,1,0,83,40,2,0,0,0,117, - 24,0,0,0,65,99,113,117,105,114,101,32,116,104,101,32, - 105,109,112,111,114,116,32,108,111,99,107,46,78,40,2,0, - 0,0,117,3,0,0,0,105,109,112,117,12,0,0,0,97, - 99,113,117,105,114,101,95,108,111,99,107,40,1,0,0,0, - 117,4,0,0,0,115,101,108,102,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,9,0,0,0,95,95,101,110,116,101, - 114,95,95,135,3,0,0,115,2,0,0,0,0,2,117,28, - 0,0,0,95,73,109,112,111,114,116,76,111,99,107,67,111, - 110,116,101,120,116,46,95,95,101,110,116,101,114,95,95,99, - 4,0,0,0,0,0,0,0,4,0,0,0,1,0,0,0, - 67,0,0,0,115,14,0,0,0,116,0,0,106,1,0,131, - 0,0,1,100,1,0,83,40,2,0,0,0,117,60,0,0, - 0,82,101,108,101,97,115,101,32,116,104,101,32,105,109,112, - 111,114,116,32,108,111,99,107,32,114,101,103,97,114,100,108, - 101,115,115,32,111,102,32,97,110,121,32,114,97,105,115,101, - 100,32,101,120,99,101,112,116,105,111,110,115,46,78,40,2, - 0,0,0,117,3,0,0,0,105,109,112,117,12,0,0,0, - 114,101,108,101,97,115,101,95,108,111,99,107,40,4,0,0, - 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,101, - 120,99,95,116,121,112,101,117,9,0,0,0,101,120,99,95, - 118,97,108,117,101,117,13,0,0,0,101,120,99,95,116,114, - 97,99,101,98,97,99,107,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,8,0,0,0,95,95,101,120,105,116,95,95, - 139,3,0,0,115,2,0,0,0,0,2,117,27,0,0,0, - 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, - 120,116,46,95,95,101,120,105,116,95,95,78,40,6,0,0, - 0,117,8,0,0,0,95,95,110,97,109,101,95,95,117,10, - 0,0,0,95,95,109,111,100,117,108,101,95,95,117,12,0, - 0,0,95,95,113,117,97,108,110,97,109,101,95,95,117,7, - 0,0,0,95,95,100,111,99,95,95,117,9,0,0,0,95, - 95,101,110,116,101,114,95,95,117,8,0,0,0,95,95,101, - 120,105,116,95,95,40,1,0,0,0,117,10,0,0,0,95, - 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,18,0,0,0,95,73,109,112,111,114, - 116,76,111,99,107,67,111,110,116,101,120,116,131,3,0,0, - 115,6,0,0,0,16,2,6,2,12,4,117,18,0,0,0, - 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, - 120,116,99,3,0,0,0,0,0,0,0,5,0,0,0,4, - 0,0,0,67,0,0,0,115,91,0,0,0,124,1,0,106, - 0,0,100,1,0,124,2,0,100,2,0,24,131,2,0,125, - 3,0,116,1,0,124,3,0,131,1,0,124,2,0,107,0, - 0,114,55,0,116,2,0,100,3,0,131,1,0,130,1,0, - 110,0,0,124,3,0,100,4,0,25,125,4,0,124,0,0, - 114,87,0,100,5,0,106,3,0,124,4,0,124,0,0,131, - 2,0,83,124,4,0,83,40,6,0,0,0,117,50,0,0, - 0,82,101,115,111,108,118,101,32,97,32,114,101,108,97,116, - 105,118,101,32,109,111,100,117,108,101,32,110,97,109,101,32, - 116,111,32,97,110,32,97,98,115,111,108,117,116,101,32,111, - 110,101,46,117,1,0,0,0,46,105,1,0,0,0,117,50, - 0,0,0,97,116,116,101,109,112,116,101,100,32,114,101,108, - 97,116,105,118,101,32,105,109,112,111,114,116,32,98,101,121, - 111,110,100,32,116,111,112,45,108,101,118,101,108,32,112,97, - 99,107,97,103,101,105,0,0,0,0,117,7,0,0,0,123, - 48,125,46,123,49,125,40,4,0,0,0,117,6,0,0,0, - 114,115,112,108,105,116,117,3,0,0,0,108,101,110,117,10, - 0,0,0,86,97,108,117,101,69,114,114,111,114,117,6,0, - 0,0,102,111,114,109,97,116,40,5,0,0,0,117,4,0, - 0,0,110,97,109,101,117,7,0,0,0,112,97,99,107,97, - 103,101,117,5,0,0,0,108,101,118,101,108,117,4,0,0, - 0,98,105,116,115,117,4,0,0,0,98,97,115,101,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,13,0,0,0,95, - 114,101,115,111,108,118,101,95,110,97,109,101,144,3,0,0, - 115,10,0,0,0,0,2,22,1,18,1,15,1,10,1,117, - 13,0,0,0,95,114,101,115,111,108,118,101,95,110,97,109, - 101,99,2,0,0,0,0,0,0,0,5,0,0,0,4,0, - 0,0,67,0,0,0,115,104,0,0,0,116,0,0,106,1, - 0,116,2,0,23,125,2,0,120,84,0,124,2,0,68,93, - 72,0,125,3,0,124,3,0,106,3,0,124,0,0,124,1, - 0,131,2,0,125,4,0,124,4,0,100,1,0,107,9,0, - 114,20,0,124,0,0,116,0,0,106,5,0,107,7,0,114, - 75,0,124,4,0,83,116,0,0,106,5,0,124,0,0,25, - 106,6,0,83,113,20,0,113,20,0,87,100,1,0,83,100, - 1,0,83,40,2,0,0,0,117,23,0,0,0,70,105,110, - 100,32,97,32,109,111,100,117,108,101,39,115,32,108,111,97, - 100,101,114,46,78,40,7,0,0,0,117,3,0,0,0,115, - 121,115,117,9,0,0,0,109,101,116,97,95,112,97,116,104, - 117,19,0,0,0,95,73,77,80,76,73,67,73,84,95,77, - 69,84,65,95,80,65,84,72,117,11,0,0,0,102,105,110, - 100,95,109,111,100,117,108,101,117,4,0,0,0,78,111,110, - 101,117,7,0,0,0,109,111,100,117,108,101,115,117,10,0, - 0,0,95,95,108,111,97,100,101,114,95,95,40,5,0,0, - 0,117,4,0,0,0,110,97,109,101,117,4,0,0,0,112, - 97,116,104,117,9,0,0,0,109,101,116,97,95,112,97,116, - 104,117,6,0,0,0,102,105,110,100,101,114,117,6,0,0, - 0,108,111,97,100,101,114,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,12,0,0,0,95,102,105,110,100,95,109,111, - 100,117,108,101,153,3,0,0,115,16,0,0,0,0,2,13, - 1,13,1,18,1,12,2,15,1,4,2,21,2,117,12,0, - 0,0,95,102,105,110,100,95,109,111,100,117,108,101,99,3, - 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, - 0,0,0,115,194,0,0,0,116,0,0,124,0,0,116,1, - 0,131,2,0,115,45,0,116,2,0,100,1,0,106,3,0, - 116,4,0,124,0,0,131,1,0,131,1,0,131,1,0,130, - 1,0,110,0,0,124,2,0,100,2,0,107,0,0,114,72, - 0,116,5,0,100,3,0,131,1,0,130,1,0,110,0,0, - 124,1,0,114,156,0,116,0,0,124,1,0,116,1,0,131, - 2,0,115,108,0,116,2,0,100,4,0,131,1,0,130,1, - 0,113,156,0,124,1,0,116,6,0,106,7,0,107,7,0, - 114,156,0,100,5,0,125,3,0,116,8,0,124,3,0,106, - 3,0,124,1,0,131,1,0,131,1,0,130,1,0,113,156, - 0,110,0,0,124,0,0,12,114,190,0,124,2,0,100,2, - 0,107,2,0,114,190,0,116,5,0,100,6,0,131,1,0, - 130,1,0,110,0,0,100,7,0,83,40,8,0,0,0,117, - 28,0,0,0,86,101,114,105,102,121,32,97,114,103,117,109, - 101,110,116,115,32,97,114,101,32,34,115,97,110,101,34,46, - 117,31,0,0,0,109,111,100,117,108,101,32,110,97,109,101, - 32,109,117,115,116,32,98,101,32,115,116,114,44,32,110,111, - 116,32,123,125,105,0,0,0,0,117,18,0,0,0,108,101, - 118,101,108,32,109,117,115,116,32,98,101,32,62,61,32,48, - 117,31,0,0,0,95,95,112,97,99,107,97,103,101,95,95, - 32,110,111,116,32,115,101,116,32,116,111,32,97,32,115,116, - 114,105,110,103,117,62,0,0,0,80,97,114,101,110,116,32, - 109,111,100,117,108,101,32,123,48,33,114,125,32,110,111,116, - 32,108,111,97,100,101,100,44,32,99,97,110,110,111,116,32, - 112,101,114,102,111,114,109,32,114,101,108,97,116,105,118,101, - 32,105,109,112,111,114,116,117,17,0,0,0,69,109,112,116, - 121,32,109,111,100,117,108,101,32,110,97,109,101,78,40,9, - 0,0,0,117,10,0,0,0,105,115,105,110,115,116,97,110, - 99,101,117,3,0,0,0,115,116,114,117,9,0,0,0,84, - 121,112,101,69,114,114,111,114,117,6,0,0,0,102,111,114, - 109,97,116,117,4,0,0,0,116,121,112,101,117,10,0,0, - 0,86,97,108,117,101,69,114,114,111,114,117,3,0,0,0, - 115,121,115,117,7,0,0,0,109,111,100,117,108,101,115,117, - 11,0,0,0,83,121,115,116,101,109,69,114,114,111,114,40, - 4,0,0,0,117,4,0,0,0,110,97,109,101,117,7,0, - 0,0,112,97,99,107,97,103,101,117,5,0,0,0,108,101, - 118,101,108,117,3,0,0,0,109,115,103,40,0,0,0,0, - 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, - 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, - 116,115,116,114,97,112,62,117,13,0,0,0,95,115,97,110, - 105,116,121,95,99,104,101,99,107,168,3,0,0,115,24,0, - 0,0,0,2,15,1,30,1,12,1,15,1,6,1,15,1, - 15,1,15,1,6,2,27,1,19,1,117,13,0,0,0,95, - 115,97,110,105,116,121,95,99,104,101,99,107,117,20,0,0, - 0,78,111,32,109,111,100,117,108,101,32,110,97,109,101,100, - 32,123,33,114,125,99,2,0,0,0,0,0,0,0,8,0, - 0,0,20,0,0,0,67,0,0,0,115,207,1,0,0,100, - 9,0,125,2,0,124,0,0,106,1,0,100,1,0,131,1, - 0,100,2,0,25,125,3,0,124,3,0,114,175,0,124,3, - 0,116,2,0,106,3,0,107,7,0,114,59,0,124,1,0, - 124,3,0,131,1,0,1,110,0,0,124,0,0,116,2,0, - 106,3,0,107,6,0,114,85,0,116,2,0,106,3,0,124, - 0,0,25,83,116,2,0,106,3,0,124,3,0,25,125,4, - 0,121,13,0,124,4,0,106,4,0,125,2,0,87,113,175, - 0,4,116,5,0,107,10,0,114,171,0,1,1,1,116,6, - 0,100,3,0,23,106,7,0,124,0,0,124,3,0,131,2, - 0,125,5,0,116,8,0,124,5,0,100,4,0,124,0,0, - 131,1,1,130,1,0,89,113,175,0,88,110,0,0,116,9, - 0,124,0,0,124,2,0,131,2,0,125,6,0,124,6,0, - 100,9,0,107,8,0,114,232,0,116,8,0,116,6,0,106, - 7,0,124,0,0,131,1,0,100,4,0,124,0,0,131,1, - 1,130,1,0,110,62,0,124,0,0,116,2,0,106,3,0, - 107,6,0,114,7,1,116,2,0,106,3,0,124,0,0,25, - 125,7,0,110,31,0,124,6,0,106,10,0,124,0,0,131, - 1,0,125,7,0,116,11,0,100,5,0,124,0,0,124,6, - 0,131,3,0,1,124,3,0,114,89,1,116,2,0,106,3, - 0,124,3,0,25,125,4,0,116,12,0,124,4,0,124,0, - 0,106,1,0,100,1,0,131,1,0,100,6,0,25,124,7, - 0,131,3,0,1,110,0,0,116,13,0,124,7,0,100,7, - 0,131,2,0,12,115,120,1,124,7,0,106,14,0,100,9, - 0,107,8,0,114,203,1,121,59,0,124,7,0,106,15,0, - 124,7,0,95,14,0,116,13,0,124,7,0,100,8,0,131, - 2,0,115,178,1,124,7,0,106,14,0,106,1,0,100,1, - 0,131,1,0,100,2,0,25,124,7,0,95,14,0,110,0, - 0,87,113,203,1,4,116,5,0,107,10,0,114,199,1,1, - 1,1,89,113,203,1,88,110,0,0,124,7,0,83,40,10, - 0,0,0,117,25,0,0,0,70,105,110,100,32,97,110,100, - 32,108,111,97,100,32,116,104,101,32,109,111,100,117,108,101, - 46,117,1,0,0,0,46,105,0,0,0,0,117,21,0,0, - 0,59,32,123,125,32,105,115,32,110,111,116,32,97,32,112, - 97,99,107,97,103,101,117,4,0,0,0,110,97,109,101,117, - 18,0,0,0,105,109,112,111,114,116,32,123,33,114,125,32, - 35,32,123,33,114,125,105,2,0,0,0,117,11,0,0,0, - 95,95,112,97,99,107,97,103,101,95,95,117,8,0,0,0, - 95,95,112,97,116,104,95,95,78,40,16,0,0,0,117,4, - 0,0,0,78,111,110,101,117,10,0,0,0,114,112,97,114, - 116,105,116,105,111,110,117,3,0,0,0,115,121,115,117,7, - 0,0,0,109,111,100,117,108,101,115,117,8,0,0,0,95, - 95,112,97,116,104,95,95,117,14,0,0,0,65,116,116,114, - 105,98,117,116,101,69,114,114,111,114,117,8,0,0,0,95, - 69,82,82,95,77,83,71,117,6,0,0,0,102,111,114,109, - 97,116,117,11,0,0,0,73,109,112,111,114,116,69,114,114, - 111,114,117,12,0,0,0,95,102,105,110,100,95,109,111,100, - 117,108,101,117,11,0,0,0,108,111,97,100,95,109,111,100, - 117,108,101,117,15,0,0,0,118,101,114,98,111,115,101,95, - 109,101,115,115,97,103,101,117,7,0,0,0,115,101,116,97, - 116,116,114,117,7,0,0,0,104,97,115,97,116,116,114,117, - 11,0,0,0,95,95,112,97,99,107,97,103,101,95,95,117, - 8,0,0,0,95,95,110,97,109,101,95,95,40,8,0,0, - 0,117,4,0,0,0,110,97,109,101,117,7,0,0,0,105, - 109,112,111,114,116,95,117,4,0,0,0,112,97,116,104,117, - 6,0,0,0,112,97,114,101,110,116,117,13,0,0,0,112, - 97,114,101,110,116,95,109,111,100,117,108,101,117,3,0,0, - 0,109,115,103,117,6,0,0,0,108,111,97,100,101,114,117, - 6,0,0,0,109,111,100,117,108,101,40,0,0,0,0,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,14,0,0,0,95,102,105,110,100, - 95,97,110,100,95,108,111,97,100,189,3,0,0,115,62,0, - 0,0,0,2,6,1,19,1,6,1,15,1,13,2,15,1, - 11,2,13,1,3,1,13,1,13,1,22,1,26,1,15,1, - 12,1,30,1,15,2,16,2,15,1,16,1,6,2,13,1, - 32,2,31,1,3,1,12,1,15,1,32,1,13,1,8,1, - 117,14,0,0,0,95,102,105,110,100,95,97,110,100,95,108, - 111,97,100,105,0,0,0,0,99,3,0,0,0,0,0,0, - 0,5,0,0,0,18,0,0,0,67,0,0,0,115,172,0, - 0,0,116,0,0,124,0,0,124,1,0,124,2,0,131,3, - 0,1,124,2,0,100,1,0,107,4,0,114,49,0,116,1, - 0,124,0,0,124,1,0,124,2,0,131,3,0,125,0,0, - 110,0,0,116,2,0,131,0,0,143,108,0,1,121,69,0, - 116,3,0,106,4,0,124,0,0,25,125,3,0,124,3,0, - 100,4,0,107,8,0,114,123,0,100,2,0,106,6,0,124, - 0,0,131,1,0,125,4,0,116,7,0,124,4,0,100,3, - 0,124,0,0,131,1,1,130,1,0,110,0,0,124,3,0, - 83,87,110,18,0,4,116,8,0,107,10,0,114,148,0,1, - 1,1,89,110,1,0,88,116,9,0,124,0,0,116,10,0, - 131,2,0,83,87,100,4,0,81,88,100,4,0,83,40,5, - 0,0,0,117,50,1,0,0,73,109,112,111,114,116,32,97, - 110,100,32,114,101,116,117,114,110,32,116,104,101,32,109,111, - 100,117,108,101,32,98,97,115,101,100,32,111,110,32,105,116, - 115,32,110,97,109,101,44,32,116,104,101,32,112,97,99,107, - 97,103,101,32,116,104,101,32,99,97,108,108,32,105,115,10, - 32,32,32,32,98,101,105,110,103,32,109,97,100,101,32,102, - 114,111,109,44,32,97,110,100,32,116,104,101,32,108,101,118, - 101,108,32,97,100,106,117,115,116,109,101,110,116,46,10,10, - 32,32,32,32,84,104,105,115,32,102,117,110,99,116,105,111, - 110,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101, - 32,103,114,101,97,116,101,115,116,32,99,111,109,109,111,110, - 32,100,101,110,111,109,105,110,97,116,111,114,32,111,102,32, - 102,117,110,99,116,105,111,110,97,108,105,116,121,10,32,32, - 32,32,98,101,116,119,101,101,110,32,105,109,112,111,114,116, - 95,109,111,100,117,108,101,32,97,110,100,32,95,95,105,109, - 112,111,114,116,95,95,46,32,84,104,105,115,32,105,110,99, - 108,117,100,101,115,32,115,101,116,116,105,110,103,32,95,95, - 112,97,99,107,97,103,101,95,95,32,105,102,10,32,32,32, - 32,116,104,101,32,108,111,97,100,101,114,32,100,105,100,32, - 110,111,116,46,10,10,32,32,32,32,105,0,0,0,0,117, - 40,0,0,0,105,109,112,111,114,116,32,111,102,32,123,125, - 32,104,97,108,116,101,100,59,32,78,111,110,101,32,105,110, - 32,115,121,115,46,109,111,100,117,108,101,115,117,4,0,0, - 0,110,97,109,101,78,40,11,0,0,0,117,13,0,0,0, - 95,115,97,110,105,116,121,95,99,104,101,99,107,117,13,0, - 0,0,95,114,101,115,111,108,118,101,95,110,97,109,101,117, - 18,0,0,0,95,73,109,112,111,114,116,76,111,99,107,67, - 111,110,116,101,120,116,117,3,0,0,0,115,121,115,117,7, - 0,0,0,109,111,100,117,108,101,115,117,4,0,0,0,78, - 111,110,101,117,6,0,0,0,102,111,114,109,97,116,117,11, - 0,0,0,73,109,112,111,114,116,69,114,114,111,114,117,8, - 0,0,0,75,101,121,69,114,114,111,114,117,14,0,0,0, - 95,102,105,110,100,95,97,110,100,95,108,111,97,100,117,11, - 0,0,0,95,103,99,100,95,105,109,112,111,114,116,40,5, - 0,0,0,117,4,0,0,0,110,97,109,101,117,7,0,0, - 0,112,97,99,107,97,103,101,117,5,0,0,0,108,101,118, - 101,108,117,6,0,0,0,109,111,100,117,108,101,117,7,0, - 0,0,109,101,115,115,97,103,101,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,11,0,0,0,95,103,99,100,95,105, - 109,112,111,114,116,230,3,0,0,115,28,0,0,0,0,9, - 16,1,12,1,21,1,10,1,3,1,13,1,12,1,6,1, - 9,1,21,1,8,1,13,1,5,1,117,11,0,0,0,95, - 103,99,100,95,105,109,112,111,114,116,99,3,0,0,0,0, - 0,0,0,4,0,0,0,13,0,0,0,3,0,0,0,115, - 179,0,0,0,116,0,0,136,0,0,100,1,0,131,2,0, - 114,175,0,100,2,0,124,1,0,107,6,0,114,86,0,116, - 0,0,136,0,0,100,3,0,131,2,0,114,86,0,116,1, - 0,124,1,0,131,1,0,125,1,0,124,1,0,106,2,0, - 100,2,0,131,1,0,1,124,1,0,106,3,0,136,0,0, - 106,4,0,131,1,0,1,110,0,0,120,86,0,135,0,0, - 102,1,0,100,4,0,100,5,0,134,0,0,124,1,0,68, - 131,1,0,68,93,56,0,125,3,0,121,29,0,124,2,0, - 100,6,0,106,5,0,136,0,0,106,6,0,124,3,0,131, - 2,0,131,1,0,1,87,113,112,0,4,116,7,0,107,10, - 0,114,167,0,1,1,1,89,113,112,0,88,113,112,0,87, - 110,0,0,136,0,0,83,40,7,0,0,0,117,238,0,0, - 0,70,105,103,117,114,101,32,111,117,116,32,119,104,97,116, - 32,95,95,105,109,112,111,114,116,95,95,32,115,104,111,117, - 108,100,32,114,101,116,117,114,110,46,10,10,32,32,32,32, - 84,104,101,32,105,109,112,111,114,116,95,32,112,97,114,97, - 109,101,116,101,114,32,105,115,32,97,32,99,97,108,108,97, - 98,108,101,32,119,104,105,99,104,32,116,97,107,101,115,32, - 116,104,101,32,110,97,109,101,32,111,102,32,109,111,100,117, - 108,101,32,116,111,10,32,32,32,32,105,109,112,111,114,116, - 46,32,73,116,32,105,115,32,114,101,113,117,105,114,101,100, - 32,116,111,32,100,101,99,111,117,112,108,101,32,116,104,101, - 32,102,117,110,99,116,105,111,110,32,102,114,111,109,32,97, - 115,115,117,109,105,110,103,32,105,109,112,111,114,116,108,105, - 98,39,115,10,32,32,32,32,105,109,112,111,114,116,32,105, - 109,112,108,101,109,101,110,116,97,116,105,111,110,32,105,115, - 32,100,101,115,105,114,101,100,46,10,10,32,32,32,32,117, - 8,0,0,0,95,95,112,97,116,104,95,95,117,1,0,0, - 0,42,117,7,0,0,0,95,95,97,108,108,95,95,99,1, - 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,51, - 0,0,0,115,36,0,0,0,124,0,0,93,26,0,125,1, - 0,116,0,0,136,0,0,124,1,0,131,2,0,115,3,0, - 124,1,0,86,1,113,3,0,100,0,0,83,40,1,0,0, - 0,78,40,1,0,0,0,117,7,0,0,0,104,97,115,97, - 116,116,114,40,2,0,0,0,117,2,0,0,0,46,48,117, - 1,0,0,0,121,40,1,0,0,0,117,6,0,0,0,109, - 111,100,117,108,101,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,9,0,0, - 0,60,103,101,110,101,120,112,114,62,14,4,0,0,115,2, - 0,0,0,6,0,117,35,0,0,0,95,104,97,110,100,108, - 101,95,102,114,111,109,108,105,115,116,46,60,108,111,99,97, - 108,115,62,46,60,103,101,110,101,120,112,114,62,117,7,0, - 0,0,123,48,125,46,123,49,125,40,8,0,0,0,117,7, - 0,0,0,104,97,115,97,116,116,114,117,4,0,0,0,108, - 105,115,116,117,6,0,0,0,114,101,109,111,118,101,117,6, - 0,0,0,101,120,116,101,110,100,117,7,0,0,0,95,95, - 97,108,108,95,95,117,6,0,0,0,102,111,114,109,97,116, - 117,8,0,0,0,95,95,110,97,109,101,95,95,117,11,0, - 0,0,73,109,112,111,114,116,69,114,114,111,114,40,4,0, - 0,0,117,6,0,0,0,109,111,100,117,108,101,117,8,0, - 0,0,102,114,111,109,108,105,115,116,117,7,0,0,0,105, - 109,112,111,114,116,95,117,1,0,0,0,120,40,0,0,0, - 0,40,1,0,0,0,117,6,0,0,0,109,111,100,117,108, - 101,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,16,0,0,0,95,104,97,110,100,108,101,95, - 102,114,111,109,108,105,115,116,255,3,0,0,115,22,0,0, - 0,0,10,15,1,27,1,12,1,13,1,19,1,32,1,3, - 1,29,1,13,1,12,1,117,16,0,0,0,95,104,97,110, - 100,108,101,95,102,114,111,109,108,105,115,116,99,1,0,0, - 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, - 0,115,78,0,0,0,124,0,0,106,0,0,100,1,0,131, - 1,0,125,1,0,124,1,0,100,6,0,107,8,0,114,74, - 0,124,0,0,100,2,0,25,125,1,0,100,3,0,124,0, - 0,107,7,0,114,74,0,124,1,0,106,2,0,100,4,0, - 131,1,0,100,5,0,25,125,1,0,113,74,0,110,0,0, - 124,1,0,83,40,7,0,0,0,117,167,0,0,0,67,97, - 108,99,117,108,97,116,101,32,119,104,97,116,32,95,95,112, - 97,99,107,97,103,101,95,95,32,115,104,111,117,108,100,32, - 98,101,46,10,10,32,32,32,32,95,95,112,97,99,107,97, - 103,101,95,95,32,105,115,32,110,111,116,32,103,117,97,114, - 97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,102, - 105,110,101,100,32,111,114,32,99,111,117,108,100,32,98,101, - 32,115,101,116,32,116,111,32,78,111,110,101,10,32,32,32, - 32,116,111,32,114,101,112,114,101,115,101,110,116,32,116,104, - 97,116,32,105,116,115,32,112,114,111,112,101,114,32,118,97, - 108,117,101,32,105,115,32,117,110,107,110,111,119,110,46,10, - 10,32,32,32,32,117,11,0,0,0,95,95,112,97,99,107, - 97,103,101,95,95,117,8,0,0,0,95,95,110,97,109,101, - 95,95,117,8,0,0,0,95,95,112,97,116,104,95,95,117, - 1,0,0,0,46,105,0,0,0,0,78,40,3,0,0,0, - 117,3,0,0,0,103,101,116,117,4,0,0,0,78,111,110, - 101,117,10,0,0,0,114,112,97,114,116,105,116,105,111,110, - 40,2,0,0,0,117,7,0,0,0,103,108,111,98,97,108, - 115,117,7,0,0,0,112,97,99,107,97,103,101,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,17,0,0,0,95,99, - 97,108,99,95,95,95,112,97,99,107,97,103,101,95,95,22, - 4,0,0,115,12,0,0,0,0,7,15,1,12,1,10,1, - 12,1,25,1,117,17,0,0,0,95,99,97,108,99,95,95, - 95,112,97,99,107,97,103,101,95,95,99,5,0,0,0,0, - 0,0,0,9,0,0,0,5,0,0,0,67,0,0,0,115, - 235,0,0,0,124,4,0,100,1,0,107,2,0,114,27,0, - 116,0,0,124,0,0,131,1,0,125,5,0,110,30,0,116, - 1,0,124,1,0,131,1,0,125,6,0,116,0,0,124,0, - 0,124,6,0,124,4,0,131,3,0,125,5,0,124,3,0, - 115,215,0,124,4,0,100,1,0,107,2,0,114,130,0,124, - 0,0,106,2,0,100,2,0,131,1,0,125,7,0,124,7, - 0,100,5,0,107,2,0,114,106,0,124,5,0,83,116,3, - 0,106,4,0,124,0,0,100,4,0,124,7,0,133,2,0, - 25,25,83,113,231,0,124,0,0,115,140,0,124,5,0,83, - 116,5,0,124,0,0,131,1,0,116,5,0,124,0,0,106, - 6,0,100,2,0,131,1,0,100,1,0,25,131,1,0,24, - 125,8,0,116,3,0,106,4,0,124,5,0,106,7,0,100, - 4,0,116,5,0,124,5,0,106,7,0,131,1,0,124,8, - 0,24,133,2,0,25,25,83,110,16,0,116,8,0,124,5, - 0,124,3,0,116,0,0,131,3,0,83,100,4,0,83,40, - 6,0,0,0,117,214,1,0,0,73,109,112,111,114,116,32, - 97,32,109,111,100,117,108,101,46,10,10,32,32,32,32,84, - 104,101,32,39,103,108,111,98,97,108,115,39,32,97,114,103, - 117,109,101,110,116,32,105,115,32,117,115,101,100,32,116,111, - 32,105,110,102,101,114,32,119,104,101,114,101,32,116,104,101, - 32,105,109,112,111,114,116,32,105,115,32,111,99,99,117,114, - 105,110,103,32,102,114,111,109,10,32,32,32,32,116,111,32, - 104,97,110,100,108,101,32,114,101,108,97,116,105,118,101,32, - 105,109,112,111,114,116,115,46,32,84,104,101,32,39,108,111, - 99,97,108,115,39,32,97,114,103,117,109,101,110,116,32,105, - 115,32,105,103,110,111,114,101,100,46,32,84,104,101,10,32, - 32,32,32,39,102,114,111,109,108,105,115,116,39,32,97,114, - 103,117,109,101,110,116,32,115,112,101,99,105,102,105,101,115, - 32,119,104,97,116,32,115,104,111,117,108,100,32,101,120,105, - 115,116,32,97,115,32,97,116,116,114,105,98,117,116,101,115, - 32,111,110,32,116,104,101,32,109,111,100,117,108,101,10,32, - 32,32,32,98,101,105,110,103,32,105,109,112,111,114,116,101, - 100,32,40,101,46,103,46,32,96,96,102,114,111,109,32,109, - 111,100,117,108,101,32,105,109,112,111,114,116,32,60,102,114, - 111,109,108,105,115,116,62,96,96,41,46,32,32,84,104,101, - 32,39,108,101,118,101,108,39,10,32,32,32,32,97,114,103, - 117,109,101,110,116,32,114,101,112,114,101,115,101,110,116,115, - 32,116,104,101,32,112,97,99,107,97,103,101,32,108,111,99, - 97,116,105,111,110,32,116,111,32,105,109,112,111,114,116,32, - 102,114,111,109,32,105,110,32,97,32,114,101,108,97,116,105, - 118,101,10,32,32,32,32,105,109,112,111,114,116,32,40,101, - 46,103,46,32,96,96,102,114,111,109,32,46,46,112,107,103, - 32,105,109,112,111,114,116,32,109,111,100,96,96,32,119,111, - 117,108,100,32,104,97,118,101,32,97,32,39,108,101,118,101, - 108,39,32,111,102,32,50,41,46,10,10,32,32,32,32,105, - 0,0,0,0,117,1,0,0,0,46,105,1,0,0,0,78, - 105,255,255,255,255,40,9,0,0,0,117,11,0,0,0,95, - 103,99,100,95,105,109,112,111,114,116,117,17,0,0,0,95, - 99,97,108,99,95,95,95,112,97,99,107,97,103,101,95,95, - 117,4,0,0,0,102,105,110,100,117,3,0,0,0,115,121, - 115,117,7,0,0,0,109,111,100,117,108,101,115,117,3,0, - 0,0,108,101,110,117,9,0,0,0,112,97,114,116,105,116, - 105,111,110,117,8,0,0,0,95,95,110,97,109,101,95,95, - 117,16,0,0,0,95,104,97,110,100,108,101,95,102,114,111, - 109,108,105,115,116,40,9,0,0,0,117,4,0,0,0,110, - 97,109,101,117,7,0,0,0,103,108,111,98,97,108,115,117, - 6,0,0,0,108,111,99,97,108,115,117,8,0,0,0,102, - 114,111,109,108,105,115,116,117,5,0,0,0,108,101,118,101, - 108,117,6,0,0,0,109,111,100,117,108,101,117,7,0,0, - 0,112,97,99,107,97,103,101,117,5,0,0,0,105,110,100, - 101,120,117,7,0,0,0,99,117,116,95,111,102,102,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,95, - 95,105,109,112,111,114,116,95,95,37,4,0,0,115,30,0, - 0,0,0,11,12,1,15,2,12,1,18,1,6,3,12,1, - 15,1,12,1,4,2,24,1,6,1,4,2,35,1,40,2, - 117,10,0,0,0,95,95,105,109,112,111,114,116,95,95,99, - 2,0,0,0,0,0,0,0,9,0,0,0,12,0,0,0, - 67,0,0,0,115,109,1,0,0,124,1,0,97,0,0,124, - 0,0,97,1,0,120,47,0,116,0,0,116,1,0,102,2, - 0,68,93,33,0,125,2,0,116,2,0,124,2,0,100,1, - 0,131,2,0,115,25,0,116,3,0,124,2,0,95,4,0, - 113,25,0,113,25,0,87,116,1,0,106,5,0,116,6,0, - 25,125,3,0,120,76,0,100,17,0,68,93,68,0,125,4, - 0,124,4,0,116,1,0,106,5,0,107,7,0,114,121,0, - 116,3,0,106,7,0,124,4,0,131,1,0,125,5,0,110, - 13,0,116,1,0,106,5,0,124,4,0,25,125,5,0,116, - 8,0,124,3,0,124,4,0,124,5,0,131,3,0,1,113, - 82,0,87,120,153,0,100,18,0,100,19,0,100,20,0,103, - 3,0,68,93,124,0,92,2,0,125,6,0,125,7,0,124, - 6,0,116,1,0,106,5,0,107,6,0,114,214,0,116,1, - 0,106,5,0,124,6,0,25,125,8,0,80,113,170,0,121, - 56,0,116,3,0,106,7,0,124,6,0,131,1,0,125,8, - 0,124,6,0,100,10,0,107,2,0,114,12,1,100,11,0, - 116,1,0,106,9,0,107,6,0,114,12,1,100,7,0,125, - 7,0,110,0,0,80,87,113,170,0,4,116,10,0,107,10, - 0,114,37,1,1,1,1,119,170,0,89,113,170,0,88,113, - 170,0,87,116,10,0,100,12,0,131,1,0,130,1,0,116, - 8,0,124,3,0,100,13,0,124,8,0,131,3,0,1,116, - 8,0,124,3,0,100,14,0,124,7,0,131,3,0,1,116, - 8,0,124,3,0,100,15,0,116,11,0,131,0,0,131,3, - 0,1,100,16,0,83,40,21,0,0,0,117,249,0,0,0, - 83,101,116,117,112,32,105,109,112,111,114,116,108,105,98,32, - 98,121,32,105,109,112,111,114,116,105,110,103,32,110,101,101, - 100,101,100,32,98,117,105,108,116,45,105,110,32,109,111,100, - 117,108,101,115,32,97,110,100,32,105,110,106,101,99,116,105, - 110,103,32,116,104,101,109,10,32,32,32,32,105,110,116,111, - 32,116,104,101,32,103,108,111,98,97,108,32,110,97,109,101, - 115,112,97,99,101,46,10,10,32,32,32,32,65,115,32,115, - 121,115,32,105,115,32,110,101,101,100,101,100,32,102,111,114, - 32,115,121,115,46,109,111,100,117,108,101,115,32,97,99,99, - 101,115,115,32,97,110,100,32,105,109,112,32,105,115,32,110, - 101,101,100,101,100,32,116,111,32,108,111,97,100,32,98,117, - 105,108,116,45,105,110,10,32,32,32,32,109,111,100,117,108, - 101,115,44,32,116,104,111,115,101,32,116,119,111,32,109,111, - 100,117,108,101,115,32,109,117,115,116,32,98,101,32,101,120, - 112,108,105,99,105,116,108,121,32,112,97,115,115,101,100,32, - 105,110,46,10,10,32,32,32,32,117,10,0,0,0,95,95, - 108,111,97,100,101,114,95,95,117,3,0,0,0,95,105,111, - 117,9,0,0,0,95,119,97,114,110,105,110,103,115,117,8, - 0,0,0,98,117,105,108,116,105,110,115,117,7,0,0,0, - 109,97,114,115,104,97,108,117,5,0,0,0,112,111,115,105, - 120,117,1,0,0,0,47,117,2,0,0,0,110,116,117,1, - 0,0,0,92,117,3,0,0,0,111,115,50,117,7,0,0, - 0,69,77,88,32,71,67,67,117,30,0,0,0,105,109,112, - 111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,32, - 112,111,115,105,120,32,111,114,32,110,116,117,3,0,0,0, - 95,111,115,117,8,0,0,0,112,97,116,104,95,115,101,112, - 117,11,0,0,0,95,114,101,108,97,120,95,99,97,115,101, - 78,40,4,0,0,0,117,3,0,0,0,95,105,111,117,9, - 0,0,0,95,119,97,114,110,105,110,103,115,117,8,0,0, - 0,98,117,105,108,116,105,110,115,117,7,0,0,0,109,97, - 114,115,104,97,108,40,2,0,0,0,117,5,0,0,0,112, - 111,115,105,120,117,1,0,0,0,47,40,2,0,0,0,117, - 2,0,0,0,110,116,117,1,0,0,0,92,40,2,0,0, - 0,117,3,0,0,0,111,115,50,117,1,0,0,0,92,40, - 12,0,0,0,117,3,0,0,0,105,109,112,117,3,0,0, - 0,115,121,115,117,7,0,0,0,104,97,115,97,116,116,114, - 117,15,0,0,0,66,117,105,108,116,105,110,73,109,112,111, - 114,116,101,114,117,10,0,0,0,95,95,108,111,97,100,101, - 114,95,95,117,7,0,0,0,109,111,100,117,108,101,115,117, - 8,0,0,0,95,95,110,97,109,101,95,95,117,11,0,0, - 0,108,111,97,100,95,109,111,100,117,108,101,117,7,0,0, - 0,115,101,116,97,116,116,114,117,7,0,0,0,118,101,114, - 115,105,111,110,117,11,0,0,0,73,109,112,111,114,116,69, - 114,114,111,114,117,16,0,0,0,95,109,97,107,101,95,114, - 101,108,97,120,95,99,97,115,101,40,9,0,0,0,117,10, - 0,0,0,115,121,115,95,109,111,100,117,108,101,117,10,0, - 0,0,105,109,112,95,109,111,100,117,108,101,117,6,0,0, - 0,109,111,100,117,108,101,117,11,0,0,0,115,101,108,102, - 95,109,111,100,117,108,101,117,12,0,0,0,98,117,105,108, - 116,105,110,95,110,97,109,101,117,14,0,0,0,98,117,105, - 108,116,105,110,95,109,111,100,117,108,101,117,10,0,0,0, - 98,117,105,108,116,105,110,95,111,115,117,8,0,0,0,112, - 97,116,104,95,115,101,112,117,9,0,0,0,111,115,95,109, - 111,100,117,108,101,40,0,0,0,0,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,6,0,0,0,95,115,101,116,117,112,71,4,0,0, - 115,52,0,0,0,0,9,6,1,6,2,19,1,15,1,16, - 2,13,1,13,1,15,1,18,2,13,1,20,2,28,1,15, - 1,13,1,4,2,3,1,15,2,27,1,9,1,5,1,13, - 1,12,2,12,1,16,1,16,2,117,6,0,0,0,95,115, - 101,116,117,112,99,2,0,0,0,0,0,0,0,3,0,0, - 0,3,0,0,0,67,0,0,0,115,44,0,0,0,116,0, - 0,124,0,0,124,1,0,131,2,0,1,116,1,0,106,2, - 0,125,2,0,116,2,0,116,1,0,95,2,0,124,2,0, - 116,1,0,95,3,0,100,1,0,83,40,2,0,0,0,117, - 201,0,0,0,73,110,115,116,97,108,108,32,105,109,112,111, - 114,116,108,105,98,32,97,115,32,116,104,101,32,105,109,112, - 108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,105, - 109,112,111,114,116,46,10,10,32,32,32,32,73,116,32,105, - 115,32,97,115,115,117,109,101,100,32,116,104,97,116,32,105, - 109,112,32,97,110,100,32,115,121,115,32,104,97,118,101,32, - 98,101,101,110,32,105,109,112,111,114,116,101,100,32,97,110, - 100,32,105,110,106,101,99,116,101,100,32,105,110,116,111,32, - 116,104,101,10,32,32,32,32,103,108,111,98,97,108,32,110, - 97,109,101,115,112,97,99,101,32,102,111,114,32,116,104,101, - 32,109,111,100,117,108,101,32,112,114,105,111,114,32,116,111, - 32,99,97,108,108,105,110,103,32,116,104,105,115,32,102,117, - 110,99,116,105,111,110,46,10,10,32,32,32,32,78,40,4, - 0,0,0,117,6,0,0,0,95,115,101,116,117,112,117,8, - 0,0,0,98,117,105,108,116,105,110,115,117,10,0,0,0, - 95,95,105,109,112,111,114,116,95,95,117,19,0,0,0,95, - 95,111,114,105,103,105,110,97,108,95,105,109,112,111,114,116, - 95,95,40,3,0,0,0,117,10,0,0,0,115,121,115,95, - 109,111,100,117,108,101,117,10,0,0,0,105,109,112,95,109, - 111,100,117,108,101,117,11,0,0,0,111,114,105,103,95,105, - 109,112,111,114,116,40,0,0,0,0,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,8,0,0,0,95,105,110,115,116,97,108,108,116,4, - 0,0,115,8,0,0,0,0,7,13,1,9,1,9,1,117, - 8,0,0,0,95,105,110,115,116,97,108,108,78,40,3,0, - 0,0,117,3,0,0,0,119,105,110,117,6,0,0,0,99, - 121,103,119,105,110,117,6,0,0,0,100,97,114,119,105,110, - 40,55,0,0,0,117,7,0,0,0,95,95,100,111,99,95, - 95,117,26,0,0,0,67,65,83,69,95,73,78,83,69,78, - 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, - 117,16,0,0,0,95,109,97,107,101,95,114,101,108,97,120, - 95,99,97,115,101,117,7,0,0,0,95,119,95,108,111,110, - 103,117,7,0,0,0,95,114,95,108,111,110,103,117,10,0, - 0,0,95,112,97,116,104,95,106,111,105,110,117,12,0,0, - 0,95,112,97,116,104,95,101,120,105,115,116,115,117,18,0, - 0,0,95,112,97,116,104,95,105,115,95,109,111,100,101,95, - 116,121,112,101,117,12,0,0,0,95,112,97,116,104,95,105, - 115,102,105,108,101,117,11,0,0,0,95,112,97,116,104,95, - 105,115,100,105,114,117,17,0,0,0,95,112,97,116,104,95, - 119,105,116,104,111,117,116,95,101,120,116,117,14,0,0,0, - 95,112,97,116,104,95,97,98,115,111,108,117,116,101,117,13, - 0,0,0,95,119,114,105,116,101,95,97,116,111,109,105,99, - 117,5,0,0,0,95,119,114,97,112,117,4,0,0,0,116, - 121,112,101,117,8,0,0,0,95,95,99,111,100,101,95,95, - 117,9,0,0,0,99,111,100,101,95,116,121,112,101,117,15, - 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, - 103,101,117,11,0,0,0,115,101,116,95,112,97,99,107,97, - 103,101,117,10,0,0,0,115,101,116,95,108,111,97,100,101, - 114,117,17,0,0,0,109,111,100,117,108,101,95,102,111,114, - 95,108,111,97,100,101,114,117,11,0,0,0,95,99,104,101, - 99,107,95,110,97,109,101,117,17,0,0,0,95,114,101,113, - 117,105,114,101,115,95,98,117,105,108,116,105,110,117,16,0, - 0,0,95,114,101,113,117,105,114,101,115,95,102,114,111,122, - 101,110,117,12,0,0,0,95,115,117,102,102,105,120,95,108, - 105,115,116,117,15,0,0,0,66,117,105,108,116,105,110,73, - 109,112,111,114,116,101,114,117,14,0,0,0,70,114,111,122, - 101,110,73,109,112,111,114,116,101,114,117,13,0,0,0,95, - 76,111,97,100,101,114,66,97,115,105,99,115,117,12,0,0, - 0,83,111,117,114,99,101,76,111,97,100,101,114,117,11,0, - 0,0,95,70,105,108,101,76,111,97,100,101,114,117,17,0, - 0,0,95,83,111,117,114,99,101,70,105,108,101,76,111,97, - 100,101,114,117,21,0,0,0,95,83,111,117,114,99,101,108, - 101,115,115,70,105,108,101,76,111,97,100,101,114,117,20,0, - 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,117,10,0,0,0,80,97,116,104,70, - 105,110,100,101,114,117,11,0,0,0,95,70,105,108,101,70, - 105,110,100,101,114,117,20,0,0,0,95,83,111,117,114,99, - 101,70,105,110,100,101,114,68,101,116,97,105,108,115,117,24, - 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, - 110,100,101,114,68,101,116,97,105,108,115,117,23,0,0,0, - 95,69,120,116,101,110,115,105,111,110,70,105,110,100,101,114, - 68,101,116,97,105,108,115,117,15,0,0,0,95,102,105,108, - 101,95,112,97,116,104,95,104,111,111,107,117,18,0,0,0, - 95,68,69,70,65,85,76,84,95,80,65,84,72,95,72,79, - 79,75,117,18,0,0,0,95,68,101,102,97,117,108,116,80, - 97,116,104,70,105,110,100,101,114,117,18,0,0,0,95,73, - 109,112,111,114,116,76,111,99,107,67,111,110,116,101,120,116, - 117,13,0,0,0,95,114,101,115,111,108,118,101,95,110,97, - 109,101,117,12,0,0,0,95,102,105,110,100,95,109,111,100, - 117,108,101,117,13,0,0,0,95,115,97,110,105,116,121,95, - 99,104,101,99,107,117,19,0,0,0,95,73,77,80,76,73, - 67,73,84,95,77,69,84,65,95,80,65,84,72,117,8,0, - 0,0,95,69,82,82,95,77,83,71,117,14,0,0,0,95, - 102,105,110,100,95,97,110,100,95,108,111,97,100,117,4,0, - 0,0,78,111,110,101,117,11,0,0,0,95,103,99,100,95, - 105,109,112,111,114,116,117,16,0,0,0,95,104,97,110,100, - 108,101,95,102,114,111,109,108,105,115,116,117,17,0,0,0, - 95,99,97,108,99,95,95,95,112,97,99,107,97,103,101,95, - 95,117,10,0,0,0,95,95,105,109,112,111,114,116,95,95, - 117,6,0,0,0,95,115,101,116,117,112,117,8,0,0,0, - 95,105,110,115,116,97,108,108,40,0,0,0,0,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,8,0,0,0,60,109, - 111,100,117,108,101,62,8,0,0,0,115,102,0,0,0,6, - 14,6,3,12,13,12,16,12,15,12,6,12,10,12,10,12, - 6,12,7,12,9,12,13,12,21,12,8,15,4,12,8,12, - 13,12,11,12,32,12,16,12,11,12,11,12,8,19,53,19, - 47,19,77,22,114,19,22,25,38,25,24,19,45,19,68,19, - 77,19,8,19,9,19,11,12,10,6,2,22,21,19,13,12, - 9,12,15,12,17,15,2,6,2,12,41,18,25,12,23,12, - 15,24,34,12,45, + 116,114,97,112,62,117,8,0,0,0,60,109,111,100,117,108, + 101,62,8,0,0,0,115,104,0,0,0,6,14,6,3,12, + 13,12,16,12,15,12,6,12,10,12,10,12,6,12,7,12, + 9,12,13,12,21,12,8,15,3,12,11,12,8,12,13,12, + 11,12,32,12,16,12,11,12,11,12,8,19,53,19,47,19, + 77,22,114,19,22,25,38,25,24,19,45,19,68,19,77,19, + 8,19,9,19,11,12,10,6,2,22,21,19,13,12,9,12, + 15,12,17,15,2,6,2,12,41,18,25,12,23,12,15,24, + 34,12,45, }; diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -225,8 +225,8 @@ if (Py_VerboseFlag) { PySys_FormatStderr("import sys # builtin\n"); } - if (PyDict_SetItemString(sys_modules, "imp", impmod) < 0) { - Py_FatalError("Py_Initialize: can't save imp to sys.modules"); + if (PyDict_SetItemString(sys_modules, "_imp", impmod) < 0) { + Py_FatalError("Py_Initialize: can't save _imp to sys.modules"); } value = PyObject_CallMethod(importlib, "_setup", "OO", sysmod, impmod); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 23:56:18 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 23:56:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Update_importlib=2Eh?= Message-ID: http://hg.python.org/cpython/rev/096653de404d changeset: 76332:096653de404d user: Brett Cannon date: Sun Apr 15 17:47:19 2012 -0400 summary: Update importlib.h files: Python/importlib.h | 5254 ++++++++++++++++---------------- 1 files changed, 2627 insertions(+), 2627 deletions(-) diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h @@ -399,2711 +399,2711 @@ 0,0,110,97,109,101,40,0,0,0,0,40,0,0,0,0, 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,10,0,0,0,110,101,119,95,109,111,100,117,108, - 101,162,0,0,0,115,2,0,0,0,0,6,117,10,0,0, - 0,110,101,119,95,109,111,100,117,108,101,99,1,0,0,0, - 0,0,0,0,2,0,0,0,4,0,0,0,71,0,0,0, - 115,75,0,0,0,116,0,0,106,1,0,106,2,0,114,71, - 0,124,0,0,106,3,0,100,6,0,131,1,0,115,40,0, - 100,3,0,124,0,0,23,125,0,0,110,0,0,116,4,0, - 124,0,0,106,5,0,124,1,0,140,0,0,100,4,0,116, - 0,0,106,6,0,131,1,1,1,110,0,0,100,5,0,83, - 40,7,0,0,0,117,61,0,0,0,80,114,105,110,116,32, - 116,104,101,32,109,101,115,115,97,103,101,32,116,111,32,115, - 116,100,101,114,114,32,105,102,32,45,118,47,80,89,84,72, - 79,78,86,69,82,66,79,83,69,32,105,115,32,116,117,114, - 110,101,100,32,111,110,46,117,1,0,0,0,35,117,7,0, - 0,0,105,109,112,111,114,116,32,117,2,0,0,0,35,32, - 117,4,0,0,0,102,105,108,101,78,40,2,0,0,0,117, - 1,0,0,0,35,117,7,0,0,0,105,109,112,111,114,116, - 32,40,7,0,0,0,117,3,0,0,0,115,121,115,117,5, - 0,0,0,102,108,97,103,115,117,7,0,0,0,118,101,114, - 98,111,115,101,117,10,0,0,0,115,116,97,114,116,115,119, - 105,116,104,117,5,0,0,0,112,114,105,110,116,117,6,0, - 0,0,102,111,114,109,97,116,117,6,0,0,0,115,116,100, - 101,114,114,40,2,0,0,0,117,7,0,0,0,109,101,115, - 115,97,103,101,117,4,0,0,0,97,114,103,115,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,15,0,0,0,118,101, - 114,98,111,115,101,95,109,101,115,115,97,103,101,173,0,0, - 0,115,8,0,0,0,0,2,12,1,15,1,13,1,117,15, - 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, - 103,101,99,1,0,0,0,0,0,0,0,2,0,0,0,3, - 0,0,0,3,0,0,0,115,35,0,0,0,135,0,0,102, - 1,0,100,1,0,100,2,0,134,0,0,125,1,0,116,0, - 0,124,1,0,136,0,0,131,2,0,1,124,1,0,83,40, - 3,0,0,0,117,39,0,0,0,83,101,116,32,95,95,112, - 97,99,107,97,103,101,95,95,32,111,110,32,116,104,101,32, - 114,101,116,117,114,110,101,100,32,109,111,100,117,108,101,46, - 99,0,0,0,0,0,0,0,0,3,0,0,0,4,0,0, - 0,31,0,0,0,115,108,0,0,0,136,0,0,124,0,0, - 124,1,0,142,0,0,125,2,0,116,0,0,124,2,0,100, - 1,0,131,2,0,12,115,46,0,124,2,0,106,1,0,100, - 0,0,107,8,0,114,104,0,124,2,0,106,3,0,124,2, - 0,95,1,0,116,0,0,124,2,0,100,2,0,131,2,0, - 115,104,0,124,2,0,106,1,0,106,4,0,100,3,0,131, - 1,0,100,4,0,25,124,2,0,95,1,0,113,104,0,110, - 0,0,124,2,0,83,40,5,0,0,0,78,117,11,0,0, - 0,95,95,112,97,99,107,97,103,101,95,95,117,8,0,0, - 0,95,95,112,97,116,104,95,95,117,1,0,0,0,46,105, - 0,0,0,0,40,5,0,0,0,117,7,0,0,0,104,97, - 115,97,116,116,114,117,11,0,0,0,95,95,112,97,99,107, - 97,103,101,95,95,117,4,0,0,0,78,111,110,101,117,8, - 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, - 114,112,97,114,116,105,116,105,111,110,40,3,0,0,0,117, - 4,0,0,0,97,114,103,115,117,6,0,0,0,107,119,97, - 114,103,115,117,6,0,0,0,109,111,100,117,108,101,40,1, - 0,0,0,117,3,0,0,0,102,120,110,40,0,0,0,0, + 112,62,117,11,0,0,0,95,110,101,119,95,109,111,100,117, + 108,101,162,0,0,0,115,2,0,0,0,0,6,117,11,0, + 0,0,95,110,101,119,95,109,111,100,117,108,101,99,1,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,71,0, + 0,0,115,75,0,0,0,116,0,0,106,1,0,106,2,0, + 114,71,0,124,0,0,106,3,0,100,6,0,131,1,0,115, + 40,0,100,3,0,124,0,0,23,125,0,0,110,0,0,116, + 4,0,124,0,0,106,5,0,124,1,0,140,0,0,100,4, + 0,116,0,0,106,6,0,131,1,1,1,110,0,0,100,5, + 0,83,40,7,0,0,0,117,61,0,0,0,80,114,105,110, + 116,32,116,104,101,32,109,101,115,115,97,103,101,32,116,111, + 32,115,116,100,101,114,114,32,105,102,32,45,118,47,80,89, + 84,72,79,78,86,69,82,66,79,83,69,32,105,115,32,116, + 117,114,110,101,100,32,111,110,46,117,1,0,0,0,35,117, + 7,0,0,0,105,109,112,111,114,116,32,117,2,0,0,0, + 35,32,117,4,0,0,0,102,105,108,101,78,40,2,0,0, + 0,117,1,0,0,0,35,117,7,0,0,0,105,109,112,111, + 114,116,32,40,7,0,0,0,117,3,0,0,0,115,121,115, + 117,5,0,0,0,102,108,97,103,115,117,7,0,0,0,118, + 101,114,98,111,115,101,117,10,0,0,0,115,116,97,114,116, + 115,119,105,116,104,117,5,0,0,0,112,114,105,110,116,117, + 6,0,0,0,102,111,114,109,97,116,117,6,0,0,0,115, + 116,100,101,114,114,40,2,0,0,0,117,7,0,0,0,109, + 101,115,115,97,103,101,117,4,0,0,0,97,114,103,115,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,15,0,0,0, + 118,101,114,98,111,115,101,95,109,101,115,115,97,103,101,173, + 0,0,0,115,8,0,0,0,0,2,12,1,15,1,13,1, + 117,15,0,0,0,118,101,114,98,111,115,101,95,109,101,115, + 115,97,103,101,99,1,0,0,0,0,0,0,0,2,0,0, + 0,3,0,0,0,3,0,0,0,115,35,0,0,0,135,0, + 0,102,1,0,100,1,0,100,2,0,134,0,0,125,1,0, + 116,0,0,124,1,0,136,0,0,131,2,0,1,124,1,0, + 83,40,3,0,0,0,117,39,0,0,0,83,101,116,32,95, + 95,112,97,99,107,97,103,101,95,95,32,111,110,32,116,104, + 101,32,114,101,116,117,114,110,101,100,32,109,111,100,117,108, + 101,46,99,0,0,0,0,0,0,0,0,3,0,0,0,4, + 0,0,0,31,0,0,0,115,108,0,0,0,136,0,0,124, + 0,0,124,1,0,142,0,0,125,2,0,116,0,0,124,2, + 0,100,1,0,131,2,0,12,115,46,0,124,2,0,106,1, + 0,100,0,0,107,8,0,114,104,0,124,2,0,106,3,0, + 124,2,0,95,1,0,116,0,0,124,2,0,100,2,0,131, + 2,0,115,104,0,124,2,0,106,1,0,106,4,0,100,3, + 0,131,1,0,100,4,0,25,124,2,0,95,1,0,113,104, + 0,110,0,0,124,2,0,83,40,5,0,0,0,78,117,11, + 0,0,0,95,95,112,97,99,107,97,103,101,95,95,117,8, + 0,0,0,95,95,112,97,116,104,95,95,117,1,0,0,0, + 46,105,0,0,0,0,40,5,0,0,0,117,7,0,0,0, + 104,97,115,97,116,116,114,117,11,0,0,0,95,95,112,97, + 99,107,97,103,101,95,95,117,4,0,0,0,78,111,110,101, + 117,8,0,0,0,95,95,110,97,109,101,95,95,117,10,0, + 0,0,114,112,97,114,116,105,116,105,111,110,40,3,0,0, + 0,117,4,0,0,0,97,114,103,115,117,6,0,0,0,107, + 119,97,114,103,115,117,6,0,0,0,109,111,100,117,108,101, + 40,1,0,0,0,117,3,0,0,0,102,120,110,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,19,0,0,0,115,101,116,95,112,97,99, + 107,97,103,101,95,119,114,97,112,112,101,114,183,0,0,0, + 115,12,0,0,0,0,1,15,1,31,1,12,1,15,1,31, + 1,117,40,0,0,0,115,101,116,95,112,97,99,107,97,103, + 101,46,60,108,111,99,97,108,115,62,46,115,101,116,95,112, + 97,99,107,97,103,101,95,119,114,97,112,112,101,114,40,1, + 0,0,0,117,5,0,0,0,95,119,114,97,112,40,2,0, + 0,0,117,3,0,0,0,102,120,110,117,19,0,0,0,115, + 101,116,95,112,97,99,107,97,103,101,95,119,114,97,112,112, + 101,114,40,0,0,0,0,40,1,0,0,0,117,3,0,0, + 0,102,120,110,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,11,0,0,0,115,101,116,95,112, + 97,99,107,97,103,101,181,0,0,0,115,6,0,0,0,0, + 2,18,7,13,1,117,11,0,0,0,115,101,116,95,112,97, + 99,107,97,103,101,99,1,0,0,0,0,0,0,0,2,0, + 0,0,3,0,0,0,3,0,0,0,115,35,0,0,0,135, + 0,0,102,1,0,100,1,0,100,2,0,134,0,0,125,1, + 0,116,0,0,124,1,0,136,0,0,131,2,0,1,124,1, + 0,83,40,3,0,0,0,117,38,0,0,0,83,101,116,32, + 95,95,108,111,97,100,101,114,95,95,32,111,110,32,116,104, + 101,32,114,101,116,117,114,110,101,100,32,109,111,100,117,108, + 101,46,99,1,0,0,0,0,0,0,0,4,0,0,0,4, + 0,0,0,31,0,0,0,115,49,0,0,0,136,0,0,124, + 0,0,124,1,0,124,2,0,142,1,0,125,3,0,116,0, + 0,124,3,0,100,1,0,131,2,0,115,45,0,124,0,0, + 124,3,0,95,1,0,110,0,0,124,3,0,83,40,2,0, + 0,0,78,117,10,0,0,0,95,95,108,111,97,100,101,114, + 95,95,40,2,0,0,0,117,7,0,0,0,104,97,115,97, + 116,116,114,117,10,0,0,0,95,95,108,111,97,100,101,114, + 95,95,40,4,0,0,0,117,4,0,0,0,115,101,108,102, + 117,4,0,0,0,97,114,103,115,117,6,0,0,0,107,119, + 97,114,103,115,117,6,0,0,0,109,111,100,117,108,101,40, + 1,0,0,0,117,3,0,0,0,102,120,110,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,18,0,0,0,115,101,116,95,108,111,97,100, + 101,114,95,119,114,97,112,112,101,114,196,0,0,0,115,8, + 0,0,0,0,1,18,1,15,1,12,1,117,38,0,0,0, + 115,101,116,95,108,111,97,100,101,114,46,60,108,111,99,97, + 108,115,62,46,115,101,116,95,108,111,97,100,101,114,95,119, + 114,97,112,112,101,114,40,1,0,0,0,117,5,0,0,0, + 95,119,114,97,112,40,2,0,0,0,117,3,0,0,0,102, + 120,110,117,18,0,0,0,115,101,116,95,108,111,97,100,101, + 114,95,119,114,97,112,112,101,114,40,0,0,0,0,40,1, + 0,0,0,117,3,0,0,0,102,120,110,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,10,0, + 0,0,115,101,116,95,108,111,97,100,101,114,194,0,0,0, + 115,6,0,0,0,0,2,18,5,13,1,117,10,0,0,0, + 115,101,116,95,108,111,97,100,101,114,99,1,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,115, + 35,0,0,0,135,0,0,102,1,0,100,1,0,100,2,0, + 134,0,0,125,1,0,116,0,0,124,1,0,136,0,0,131, + 2,0,1,124,1,0,83,40,3,0,0,0,117,28,2,0, + 0,68,101,99,111,114,97,116,111,114,32,116,111,32,104,97, + 110,100,108,101,32,115,101,108,101,99,116,105,110,103,32,116, + 104,101,32,112,114,111,112,101,114,32,109,111,100,117,108,101, + 32,102,111,114,32,108,111,97,100,101,114,115,46,10,10,32, + 32,32,32,84,104,101,32,100,101,99,111,114,97,116,101,100, + 32,102,117,110,99,116,105,111,110,32,105,115,32,112,97,115, + 115,101,100,32,116,104,101,32,109,111,100,117,108,101,32,116, + 111,32,117,115,101,32,105,110,115,116,101,97,100,32,111,102, + 32,116,104,101,32,109,111,100,117,108,101,10,32,32,32,32, + 110,97,109,101,46,32,84,104,101,32,109,111,100,117,108,101, + 32,112,97,115,115,101,100,32,105,110,32,116,111,32,116,104, + 101,32,102,117,110,99,116,105,111,110,32,105,115,32,101,105, + 116,104,101,114,32,102,114,111,109,32,115,121,115,46,109,111, + 100,117,108,101,115,32,105,102,10,32,32,32,32,105,116,32, + 97,108,114,101,97,100,121,32,101,120,105,115,116,115,32,111, + 114,32,105,115,32,97,32,110,101,119,32,109,111,100,117,108, + 101,32,119,104,105,99,104,32,104,97,115,32,95,95,110,97, + 109,101,95,95,32,115,101,116,32,97,110,100,32,105,115,32, + 105,110,115,101,114,116,101,100,10,32,32,32,32,105,110,116, + 111,32,115,121,115,46,109,111,100,117,108,101,115,46,32,73, + 102,32,97,110,32,101,120,99,101,112,116,105,111,110,32,105, + 115,32,114,97,105,115,101,100,32,97,110,100,32,116,104,101, + 32,100,101,99,111,114,97,116,111,114,32,99,114,101,97,116, + 101,100,32,116,104,101,10,32,32,32,32,109,111,100,117,108, + 101,32,105,116,32,105,115,32,115,117,98,115,101,113,117,101, + 110,116,108,121,32,114,101,109,111,118,101,100,32,102,114,111, + 109,32,115,121,115,46,109,111,100,117,108,101,115,46,10,10, + 32,32,32,32,84,104,101,32,100,101,99,111,114,97,116,111, + 114,32,97,115,115,117,109,101,115,32,116,104,97,116,32,116, + 104,101,32,100,101,99,111,114,97,116,101,100,32,102,117,110, + 99,116,105,111,110,32,116,97,107,101,115,32,116,104,101,32, + 109,111,100,117,108,101,32,110,97,109,101,32,97,115,10,32, + 32,32,32,116,104,101,32,115,101,99,111,110,100,32,97,114, + 103,117,109,101,110,116,46,10,10,32,32,32,32,99,2,0, + 0,0,0,0,0,0,6,0,0,0,11,0,0,0,31,0, + 0,0,115,124,0,0,0,116,0,0,106,1,0,106,2,0, + 124,1,0,131,1,0,125,4,0,116,3,0,124,4,0,131, + 1,0,125,5,0,124,5,0,115,64,0,116,4,0,124,1, + 0,131,1,0,125,4,0,124,4,0,116,0,0,106,1,0, + 124,1,0,60,110,0,0,121,23,0,136,0,0,124,0,0, + 124,4,0,124,2,0,124,3,0,142,2,0,83,87,110,30, + 0,1,1,1,124,5,0,115,112,0,116,0,0,106,1,0, + 124,1,0,61,110,0,0,130,0,0,89,110,1,0,88,100, + 0,0,83,40,1,0,0,0,78,40,5,0,0,0,117,3, + 0,0,0,115,121,115,117,7,0,0,0,109,111,100,117,108, + 101,115,117,3,0,0,0,103,101,116,117,4,0,0,0,98, + 111,111,108,117,11,0,0,0,95,110,101,119,95,109,111,100, + 117,108,101,40,6,0,0,0,117,4,0,0,0,115,101,108, + 102,117,8,0,0,0,102,117,108,108,110,97,109,101,117,4, + 0,0,0,97,114,103,115,117,6,0,0,0,107,119,97,114, + 103,115,117,6,0,0,0,109,111,100,117,108,101,117,9,0, + 0,0,105,115,95,114,101,108,111,97,100,40,1,0,0,0, + 117,3,0,0,0,102,120,110,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 25,0,0,0,109,111,100,117,108,101,95,102,111,114,95,108, + 111,97,100,101,114,95,119,114,97,112,112,101,114,218,0,0, + 0,115,22,0,0,0,0,1,18,1,12,1,6,4,12,1, + 16,1,3,1,23,1,3,1,6,1,13,1,117,52,0,0, + 0,109,111,100,117,108,101,95,102,111,114,95,108,111,97,100, + 101,114,46,60,108,111,99,97,108,115,62,46,109,111,100,117, + 108,101,95,102,111,114,95,108,111,97,100,101,114,95,119,114, + 97,112,112,101,114,40,1,0,0,0,117,5,0,0,0,95, + 119,114,97,112,40,2,0,0,0,117,3,0,0,0,102,120, + 110,117,25,0,0,0,109,111,100,117,108,101,95,102,111,114, + 95,108,111,97,100,101,114,95,119,114,97,112,112,101,114,40, + 0,0,0,0,40,1,0,0,0,117,3,0,0,0,102,120, + 110,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,17,0,0,0,109,111,100,117,108,101,95,102, + 111,114,95,108,111,97,100,101,114,205,0,0,0,115,6,0, + 0,0,0,13,18,15,13,1,117,17,0,0,0,109,111,100, + 117,108,101,95,102,111,114,95,108,111,97,100,101,114,99,1, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,3, + 0,0,0,115,35,0,0,0,135,0,0,102,1,0,100,1, + 0,100,2,0,134,0,0,125,1,0,116,0,0,124,1,0, + 136,0,0,131,2,0,1,124,1,0,83,40,3,0,0,0, + 117,252,0,0,0,68,101,99,111,114,97,116,111,114,32,116, + 111,32,118,101,114,105,102,121,32,116,104,97,116,32,116,104, + 101,32,109,111,100,117,108,101,32,98,101,105,110,103,32,114, + 101,113,117,101,115,116,101,100,32,109,97,116,99,104,101,115, + 32,116,104,101,32,111,110,101,32,116,104,101,10,32,32,32, + 32,108,111,97,100,101,114,32,99,97,110,32,104,97,110,100, + 108,101,46,10,10,32,32,32,32,84,104,101,32,102,105,114, + 115,116,32,97,114,103,117,109,101,110,116,32,40,115,101,108, + 102,41,32,109,117,115,116,32,100,101,102,105,110,101,32,95, + 110,97,109,101,32,119,104,105,99,104,32,116,104,101,32,115, + 101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,105, + 115,10,32,32,32,32,99,111,109,112,97,114,101,100,32,97, + 103,97,105,110,115,116,46,32,73,102,32,116,104,101,32,99, + 111,109,112,97,114,105,115,111,110,32,102,97,105,108,115,32, + 116,104,101,110,32,73,109,112,111,114,116,69,114,114,111,114, + 32,105,115,32,114,97,105,115,101,100,46,10,10,32,32,32, + 32,99,2,0,0,0,0,0,0,0,4,0,0,0,5,0, + 0,0,31,0,0,0,115,59,0,0,0,124,0,0,106,0, + 0,124,1,0,107,3,0,114,40,0,116,1,0,100,1,0, + 124,1,0,22,100,2,0,124,1,0,131,1,1,130,1,0, + 110,0,0,136,0,0,124,0,0,124,1,0,124,2,0,124, + 3,0,142,2,0,83,40,3,0,0,0,78,117,23,0,0, + 0,108,111,97,100,101,114,32,99,97,110,110,111,116,32,104, + 97,110,100,108,101,32,37,115,117,4,0,0,0,110,97,109, + 101,40,2,0,0,0,117,5,0,0,0,95,110,97,109,101, + 117,11,0,0,0,73,109,112,111,114,116,69,114,114,111,114, + 40,4,0,0,0,117,4,0,0,0,115,101,108,102,117,4, + 0,0,0,110,97,109,101,117,4,0,0,0,97,114,103,115, + 117,6,0,0,0,107,119,97,114,103,115,40,1,0,0,0, + 117,6,0,0,0,109,101,116,104,111,100,40,0,0,0,0, 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,19,0,0,0,115,101,116,95,112,97,99,107,97, - 103,101,95,119,114,97,112,112,101,114,183,0,0,0,115,12, - 0,0,0,0,1,15,1,31,1,12,1,15,1,31,1,117, - 40,0,0,0,115,101,116,95,112,97,99,107,97,103,101,46, - 60,108,111,99,97,108,115,62,46,115,101,116,95,112,97,99, - 107,97,103,101,95,119,114,97,112,112,101,114,40,1,0,0, - 0,117,5,0,0,0,95,119,114,97,112,40,2,0,0,0, - 117,3,0,0,0,102,120,110,117,19,0,0,0,115,101,116, - 95,112,97,99,107,97,103,101,95,119,114,97,112,112,101,114, - 40,0,0,0,0,40,1,0,0,0,117,3,0,0,0,102, - 120,110,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 112,62,117,19,0,0,0,95,99,104,101,99,107,95,110,97, + 109,101,95,119,114,97,112,112,101,114,245,0,0,0,115,6, + 0,0,0,0,1,15,1,25,1,117,40,0,0,0,95,99, + 104,101,99,107,95,110,97,109,101,46,60,108,111,99,97,108, + 115,62,46,95,99,104,101,99,107,95,110,97,109,101,95,119, + 114,97,112,112,101,114,40,1,0,0,0,117,5,0,0,0, + 95,119,114,97,112,40,2,0,0,0,117,6,0,0,0,109, + 101,116,104,111,100,117,19,0,0,0,95,99,104,101,99,107, + 95,110,97,109,101,95,119,114,97,112,112,101,114,40,0,0, + 0,0,40,1,0,0,0,117,6,0,0,0,109,101,116,104, + 111,100,117,29,0,0,0,60,102,114,111,122,101,110,32,105, 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,11,0,0,0,115,101,116,95,112,97,99, - 107,97,103,101,181,0,0,0,115,6,0,0,0,0,2,18, - 7,13,1,117,11,0,0,0,115,101,116,95,112,97,99,107, - 97,103,101,99,1,0,0,0,0,0,0,0,2,0,0,0, + 114,97,112,62,117,11,0,0,0,95,99,104,101,99,107,95, + 110,97,109,101,237,0,0,0,115,6,0,0,0,0,8,18, + 4,13,1,117,11,0,0,0,95,99,104,101,99,107,95,110, + 97,109,101,99,1,0,0,0,0,0,0,0,2,0,0,0, 3,0,0,0,3,0,0,0,115,35,0,0,0,135,0,0, 102,1,0,100,1,0,100,2,0,134,0,0,125,1,0,116, 0,0,124,1,0,136,0,0,131,2,0,1,124,1,0,83, - 40,3,0,0,0,117,38,0,0,0,83,101,116,32,95,95, - 108,111,97,100,101,114,95,95,32,111,110,32,116,104,101,32, - 114,101,116,117,114,110,101,100,32,109,111,100,117,108,101,46, - 99,1,0,0,0,0,0,0,0,4,0,0,0,4,0,0, - 0,31,0,0,0,115,49,0,0,0,136,0,0,124,0,0, - 124,1,0,124,2,0,142,1,0,125,3,0,116,0,0,124, - 3,0,100,1,0,131,2,0,115,45,0,124,0,0,124,3, - 0,95,1,0,110,0,0,124,3,0,83,40,2,0,0,0, - 78,117,10,0,0,0,95,95,108,111,97,100,101,114,95,95, - 40,2,0,0,0,117,7,0,0,0,104,97,115,97,116,116, - 114,117,10,0,0,0,95,95,108,111,97,100,101,114,95,95, - 40,4,0,0,0,117,4,0,0,0,115,101,108,102,117,4, - 0,0,0,97,114,103,115,117,6,0,0,0,107,119,97,114, - 103,115,117,6,0,0,0,109,111,100,117,108,101,40,1,0, - 0,0,117,3,0,0,0,102,120,110,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,18,0,0,0,115,101,116,95,108,111,97,100,101,114, - 95,119,114,97,112,112,101,114,196,0,0,0,115,8,0,0, - 0,0,1,18,1,15,1,12,1,117,38,0,0,0,115,101, - 116,95,108,111,97,100,101,114,46,60,108,111,99,97,108,115, - 62,46,115,101,116,95,108,111,97,100,101,114,95,119,114,97, - 112,112,101,114,40,1,0,0,0,117,5,0,0,0,95,119, - 114,97,112,40,2,0,0,0,117,3,0,0,0,102,120,110, - 117,18,0,0,0,115,101,116,95,108,111,97,100,101,114,95, - 119,114,97,112,112,101,114,40,0,0,0,0,40,1,0,0, - 0,117,3,0,0,0,102,120,110,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,10,0,0,0, - 115,101,116,95,108,111,97,100,101,114,194,0,0,0,115,6, - 0,0,0,0,2,18,5,13,1,117,10,0,0,0,115,101, - 116,95,108,111,97,100,101,114,99,1,0,0,0,0,0,0, - 0,2,0,0,0,3,0,0,0,3,0,0,0,115,35,0, - 0,0,135,0,0,102,1,0,100,1,0,100,2,0,134,0, - 0,125,1,0,116,0,0,124,1,0,136,0,0,131,2,0, - 1,124,1,0,83,40,3,0,0,0,117,28,2,0,0,68, - 101,99,111,114,97,116,111,114,32,116,111,32,104,97,110,100, - 108,101,32,115,101,108,101,99,116,105,110,103,32,116,104,101, - 32,112,114,111,112,101,114,32,109,111,100,117,108,101,32,102, - 111,114,32,108,111,97,100,101,114,115,46,10,10,32,32,32, - 32,84,104,101,32,100,101,99,111,114,97,116,101,100,32,102, - 117,110,99,116,105,111,110,32,105,115,32,112,97,115,115,101, - 100,32,116,104,101,32,109,111,100,117,108,101,32,116,111,32, - 117,115,101,32,105,110,115,116,101,97,100,32,111,102,32,116, - 104,101,32,109,111,100,117,108,101,10,32,32,32,32,110,97, - 109,101,46,32,84,104,101,32,109,111,100,117,108,101,32,112, - 97,115,115,101,100,32,105,110,32,116,111,32,116,104,101,32, - 102,117,110,99,116,105,111,110,32,105,115,32,101,105,116,104, - 101,114,32,102,114,111,109,32,115,121,115,46,109,111,100,117, - 108,101,115,32,105,102,10,32,32,32,32,105,116,32,97,108, - 114,101,97,100,121,32,101,120,105,115,116,115,32,111,114,32, - 105,115,32,97,32,110,101,119,32,109,111,100,117,108,101,32, - 119,104,105,99,104,32,104,97,115,32,95,95,110,97,109,101, - 95,95,32,115,101,116,32,97,110,100,32,105,115,32,105,110, - 115,101,114,116,101,100,10,32,32,32,32,105,110,116,111,32, - 115,121,115,46,109,111,100,117,108,101,115,46,32,73,102,32, - 97,110,32,101,120,99,101,112,116,105,111,110,32,105,115,32, - 114,97,105,115,101,100,32,97,110,100,32,116,104,101,32,100, - 101,99,111,114,97,116,111,114,32,99,114,101,97,116,101,100, - 32,116,104,101,10,32,32,32,32,109,111,100,117,108,101,32, - 105,116,32,105,115,32,115,117,98,115,101,113,117,101,110,116, - 108,121,32,114,101,109,111,118,101,100,32,102,114,111,109,32, - 115,121,115,46,109,111,100,117,108,101,115,46,10,10,32,32, - 32,32,84,104,101,32,100,101,99,111,114,97,116,111,114,32, - 97,115,115,117,109,101,115,32,116,104,97,116,32,116,104,101, - 32,100,101,99,111,114,97,116,101,100,32,102,117,110,99,116, - 105,111,110,32,116,97,107,101,115,32,116,104,101,32,109,111, - 100,117,108,101,32,110,97,109,101,32,97,115,10,32,32,32, - 32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117, - 109,101,110,116,46,10,10,32,32,32,32,99,2,0,0,0, - 0,0,0,0,6,0,0,0,11,0,0,0,31,0,0,0, - 115,124,0,0,0,116,0,0,106,1,0,106,2,0,124,1, - 0,131,1,0,125,4,0,116,3,0,124,4,0,131,1,0, - 125,5,0,124,5,0,115,64,0,116,4,0,124,1,0,131, - 1,0,125,4,0,124,4,0,116,0,0,106,1,0,124,1, - 0,60,110,0,0,121,23,0,136,0,0,124,0,0,124,4, - 0,124,2,0,124,3,0,142,2,0,83,87,110,30,0,1, - 1,1,124,5,0,115,112,0,116,0,0,106,1,0,124,1, - 0,61,110,0,0,130,0,0,89,110,1,0,88,100,0,0, - 83,40,1,0,0,0,78,40,5,0,0,0,117,3,0,0, - 0,115,121,115,117,7,0,0,0,109,111,100,117,108,101,115, - 117,3,0,0,0,103,101,116,117,4,0,0,0,98,111,111, - 108,117,10,0,0,0,110,101,119,95,109,111,100,117,108,101, - 40,6,0,0,0,117,4,0,0,0,115,101,108,102,117,8, - 0,0,0,102,117,108,108,110,97,109,101,117,4,0,0,0, - 97,114,103,115,117,6,0,0,0,107,119,97,114,103,115,117, - 6,0,0,0,109,111,100,117,108,101,117,9,0,0,0,105, - 115,95,114,101,108,111,97,100,40,1,0,0,0,117,3,0, - 0,0,102,120,110,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,25,0,0, - 0,109,111,100,117,108,101,95,102,111,114,95,108,111,97,100, - 101,114,95,119,114,97,112,112,101,114,218,0,0,0,115,22, - 0,0,0,0,1,18,1,12,1,6,4,12,1,16,1,3, - 1,23,1,3,1,6,1,13,1,117,52,0,0,0,109,111, - 100,117,108,101,95,102,111,114,95,108,111,97,100,101,114,46, - 60,108,111,99,97,108,115,62,46,109,111,100,117,108,101,95, - 102,111,114,95,108,111,97,100,101,114,95,119,114,97,112,112, - 101,114,40,1,0,0,0,117,5,0,0,0,95,119,114,97, - 112,40,2,0,0,0,117,3,0,0,0,102,120,110,117,25, - 0,0,0,109,111,100,117,108,101,95,102,111,114,95,108,111, - 97,100,101,114,95,119,114,97,112,112,101,114,40,0,0,0, - 0,40,1,0,0,0,117,3,0,0,0,102,120,110,117,29, - 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,17,0,0,0,109,111,100,117,108,101,95,102,111,114,95, - 108,111,97,100,101,114,205,0,0,0,115,6,0,0,0,0, - 13,18,15,13,1,117,17,0,0,0,109,111,100,117,108,101, - 95,102,111,114,95,108,111,97,100,101,114,99,1,0,0,0, - 0,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0, - 115,35,0,0,0,135,0,0,102,1,0,100,1,0,100,2, - 0,134,0,0,125,1,0,116,0,0,124,1,0,136,0,0, - 131,2,0,1,124,1,0,83,40,3,0,0,0,117,252,0, - 0,0,68,101,99,111,114,97,116,111,114,32,116,111,32,118, - 101,114,105,102,121,32,116,104,97,116,32,116,104,101,32,109, - 111,100,117,108,101,32,98,101,105,110,103,32,114,101,113,117, - 101,115,116,101,100,32,109,97,116,99,104,101,115,32,116,104, - 101,32,111,110,101,32,116,104,101,10,32,32,32,32,108,111, - 97,100,101,114,32,99,97,110,32,104,97,110,100,108,101,46, - 10,10,32,32,32,32,84,104,101,32,102,105,114,115,116,32, - 97,114,103,117,109,101,110,116,32,40,115,101,108,102,41,32, - 109,117,115,116,32,100,101,102,105,110,101,32,95,110,97,109, - 101,32,119,104,105,99,104,32,116,104,101,32,115,101,99,111, - 110,100,32,97,114,103,117,109,101,110,116,32,105,115,10,32, - 32,32,32,99,111,109,112,97,114,101,100,32,97,103,97,105, - 110,115,116,46,32,73,102,32,116,104,101,32,99,111,109,112, - 97,114,105,115,111,110,32,102,97,105,108,115,32,116,104,101, - 110,32,73,109,112,111,114,116,69,114,114,111,114,32,105,115, - 32,114,97,105,115,101,100,46,10,10,32,32,32,32,99,2, - 0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,31, - 0,0,0,115,59,0,0,0,124,0,0,106,0,0,124,1, - 0,107,3,0,114,40,0,116,1,0,100,1,0,124,1,0, - 22,100,2,0,124,1,0,131,1,1,130,1,0,110,0,0, - 136,0,0,124,0,0,124,1,0,124,2,0,124,3,0,142, - 2,0,83,40,3,0,0,0,78,117,23,0,0,0,108,111, - 97,100,101,114,32,99,97,110,110,111,116,32,104,97,110,100, - 108,101,32,37,115,117,4,0,0,0,110,97,109,101,40,2, - 0,0,0,117,5,0,0,0,95,110,97,109,101,117,11,0, - 0,0,73,109,112,111,114,116,69,114,114,111,114,40,4,0, - 0,0,117,4,0,0,0,115,101,108,102,117,4,0,0,0, - 110,97,109,101,117,4,0,0,0,97,114,103,115,117,6,0, - 0,0,107,119,97,114,103,115,40,1,0,0,0,117,6,0, - 0,0,109,101,116,104,111,100,40,0,0,0,0,117,29,0, + 40,3,0,0,0,117,49,0,0,0,68,101,99,111,114,97, + 116,111,114,32,116,111,32,118,101,114,105,102,121,32,116,104, + 101,32,110,97,109,101,100,32,109,111,100,117,108,101,32,105, + 115,32,98,117,105,108,116,45,105,110,46,99,2,0,0,0, + 0,0,0,0,2,0,0,0,4,0,0,0,19,0,0,0, + 115,58,0,0,0,124,1,0,116,0,0,106,1,0,107,7, + 0,114,45,0,116,2,0,100,1,0,106,3,0,124,1,0, + 131,1,0,100,2,0,124,1,0,131,1,1,130,1,0,110, + 0,0,136,0,0,124,0,0,124,1,0,131,2,0,83,40, + 3,0,0,0,78,117,28,0,0,0,123,48,125,32,105,115, + 32,110,111,116,32,97,32,98,117,105,108,116,45,105,110,32, + 109,111,100,117,108,101,117,4,0,0,0,110,97,109,101,40, + 4,0,0,0,117,3,0,0,0,115,121,115,117,20,0,0, + 0,98,117,105,108,116,105,110,95,109,111,100,117,108,101,95, + 110,97,109,101,115,117,11,0,0,0,73,109,112,111,114,116, + 69,114,114,111,114,117,6,0,0,0,102,111,114,109,97,116, + 40,2,0,0,0,117,4,0,0,0,115,101,108,102,117,8, + 0,0,0,102,117,108,108,110,97,109,101,40,1,0,0,0, + 117,3,0,0,0,102,120,110,40,0,0,0,0,117,29,0, 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 19,0,0,0,95,99,104,101,99,107,95,110,97,109,101,95, - 119,114,97,112,112,101,114,245,0,0,0,115,6,0,0,0, - 0,1,15,1,25,1,117,40,0,0,0,95,99,104,101,99, - 107,95,110,97,109,101,46,60,108,111,99,97,108,115,62,46, - 95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112, - 112,101,114,40,1,0,0,0,117,5,0,0,0,95,119,114, - 97,112,40,2,0,0,0,117,6,0,0,0,109,101,116,104, - 111,100,117,19,0,0,0,95,99,104,101,99,107,95,110,97, - 109,101,95,119,114,97,112,112,101,114,40,0,0,0,0,40, - 1,0,0,0,117,6,0,0,0,109,101,116,104,111,100,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,11,0,0,0,95,99,104,101,99,107,95,110,97,109, - 101,237,0,0,0,115,6,0,0,0,0,8,18,4,13,1, - 117,11,0,0,0,95,99,104,101,99,107,95,110,97,109,101, + 25,0,0,0,95,114,101,113,117,105,114,101,115,95,98,117, + 105,108,116,105,110,95,119,114,97,112,112,101,114,255,0,0, + 0,115,8,0,0,0,0,1,15,1,18,1,12,1,117,52, + 0,0,0,95,114,101,113,117,105,114,101,115,95,98,117,105, + 108,116,105,110,46,60,108,111,99,97,108,115,62,46,95,114, + 101,113,117,105,114,101,115,95,98,117,105,108,116,105,110,95, + 119,114,97,112,112,101,114,40,1,0,0,0,117,5,0,0, + 0,95,119,114,97,112,40,2,0,0,0,117,3,0,0,0, + 102,120,110,117,25,0,0,0,95,114,101,113,117,105,114,101, + 115,95,98,117,105,108,116,105,110,95,119,114,97,112,112,101, + 114,40,0,0,0,0,40,1,0,0,0,117,3,0,0,0, + 102,120,110,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,17,0,0,0,95,114,101,113,117,105, + 114,101,115,95,98,117,105,108,116,105,110,253,0,0,0,115, + 6,0,0,0,0,2,18,5,13,1,117,17,0,0,0,95, + 114,101,113,117,105,114,101,115,95,98,117,105,108,116,105,110, 99,1,0,0,0,0,0,0,0,2,0,0,0,3,0,0, 0,3,0,0,0,115,35,0,0,0,135,0,0,102,1,0, 100,1,0,100,2,0,134,0,0,125,1,0,116,0,0,124, 1,0,136,0,0,131,2,0,1,124,1,0,83,40,3,0, - 0,0,117,49,0,0,0,68,101,99,111,114,97,116,111,114, + 0,0,117,47,0,0,0,68,101,99,111,114,97,116,111,114, 32,116,111,32,118,101,114,105,102,121,32,116,104,101,32,110, - 97,109,101,100,32,109,111,100,117,108,101,32,105,115,32,98, - 117,105,108,116,45,105,110,46,99,2,0,0,0,0,0,0, - 0,2,0,0,0,4,0,0,0,19,0,0,0,115,58,0, - 0,0,124,1,0,116,0,0,106,1,0,107,7,0,114,45, - 0,116,2,0,100,1,0,106,3,0,124,1,0,131,1,0, - 100,2,0,124,1,0,131,1,1,130,1,0,110,0,0,136, - 0,0,124,0,0,124,1,0,131,2,0,83,40,3,0,0, - 0,78,117,28,0,0,0,123,48,125,32,105,115,32,110,111, - 116,32,97,32,98,117,105,108,116,45,105,110,32,109,111,100, - 117,108,101,117,4,0,0,0,110,97,109,101,40,4,0,0, - 0,117,3,0,0,0,115,121,115,117,20,0,0,0,98,117, - 105,108,116,105,110,95,109,111,100,117,108,101,95,110,97,109, - 101,115,117,11,0,0,0,73,109,112,111,114,116,69,114,114, - 111,114,117,6,0,0,0,102,111,114,109,97,116,40,2,0, - 0,0,117,4,0,0,0,115,101,108,102,117,8,0,0,0, - 102,117,108,108,110,97,109,101,40,1,0,0,0,117,3,0, - 0,0,102,120,110,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,25,0,0, - 0,95,114,101,113,117,105,114,101,115,95,98,117,105,108,116, - 105,110,95,119,114,97,112,112,101,114,255,0,0,0,115,8, - 0,0,0,0,1,15,1,18,1,12,1,117,52,0,0,0, - 95,114,101,113,117,105,114,101,115,95,98,117,105,108,116,105, + 97,109,101,100,32,109,111,100,117,108,101,32,105,115,32,102, + 114,111,122,101,110,46,99,2,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,19,0,0,0,115,58,0,0,0, + 116,0,0,106,1,0,124,1,0,131,1,0,115,45,0,116, + 2,0,100,1,0,106,3,0,124,1,0,131,1,0,100,2, + 0,124,1,0,131,1,1,130,1,0,110,0,0,136,0,0, + 124,0,0,124,1,0,131,2,0,83,40,3,0,0,0,78, + 117,26,0,0,0,123,48,125,32,105,115,32,110,111,116,32, + 97,32,102,114,111,122,101,110,32,109,111,100,117,108,101,117, + 4,0,0,0,110,97,109,101,40,4,0,0,0,117,4,0, + 0,0,95,105,109,112,117,9,0,0,0,105,115,95,102,114, + 111,122,101,110,117,11,0,0,0,73,109,112,111,114,116,69, + 114,114,111,114,117,6,0,0,0,102,111,114,109,97,116,40, + 2,0,0,0,117,4,0,0,0,115,101,108,102,117,8,0, + 0,0,102,117,108,108,110,97,109,101,40,1,0,0,0,117, + 3,0,0,0,102,120,110,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,24, + 0,0,0,95,114,101,113,117,105,114,101,115,95,102,114,111, + 122,101,110,95,119,114,97,112,112,101,114,10,1,0,0,115, + 8,0,0,0,0,1,15,1,18,1,12,1,117,50,0,0, + 0,95,114,101,113,117,105,114,101,115,95,102,114,111,122,101, 110,46,60,108,111,99,97,108,115,62,46,95,114,101,113,117, - 105,114,101,115,95,98,117,105,108,116,105,110,95,119,114,97, - 112,112,101,114,40,1,0,0,0,117,5,0,0,0,95,119, - 114,97,112,40,2,0,0,0,117,3,0,0,0,102,120,110, - 117,25,0,0,0,95,114,101,113,117,105,114,101,115,95,98, - 117,105,108,116,105,110,95,119,114,97,112,112,101,114,40,0, - 0,0,0,40,1,0,0,0,117,3,0,0,0,102,120,110, + 105,114,101,115,95,102,114,111,122,101,110,95,119,114,97,112, + 112,101,114,40,1,0,0,0,117,5,0,0,0,95,119,114, + 97,112,40,2,0,0,0,117,3,0,0,0,102,120,110,117, + 24,0,0,0,95,114,101,113,117,105,114,101,115,95,102,114, + 111,122,101,110,95,119,114,97,112,112,101,114,40,0,0,0, + 0,40,1,0,0,0,117,3,0,0,0,102,120,110,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,16,0,0,0,95,114,101,113,117,105,114,101,115,95,102, + 114,111,122,101,110,8,1,0,0,115,6,0,0,0,0,2, + 18,5,13,1,117,16,0,0,0,95,114,101,113,117,105,114, + 101,115,95,102,114,111,122,101,110,99,1,0,0,0,0,0, + 0,0,1,0,0,0,3,0,0,0,3,0,0,0,115,29, + 0,0,0,135,0,0,102,1,0,100,1,0,100,2,0,134, + 0,0,116,0,0,106,1,0,131,0,0,68,131,1,0,83, + 40,3,0,0,0,117,58,0,0,0,82,101,116,117,114,110, + 32,97,32,108,105,115,116,32,111,102,32,102,105,108,101,32, + 115,117,102,102,105,120,101,115,32,98,97,115,101,100,32,111, + 110,32,116,104,101,32,105,109,112,32,102,105,108,101,32,116, + 121,112,101,46,99,1,0,0,0,0,0,0,0,2,0,0, + 0,4,0,0,0,19,0,0,0,115,42,0,0,0,103,0, + 0,124,0,0,93,32,0,125,1,0,124,1,0,100,0,0, + 25,136,0,0,107,2,0,114,6,0,124,1,0,100,1,0, + 25,145,2,0,113,6,0,83,40,2,0,0,0,105,2,0, + 0,0,105,0,0,0,0,40,0,0,0,0,40,2,0,0, + 0,117,2,0,0,0,46,48,117,6,0,0,0,115,117,102, + 102,105,120,40,1,0,0,0,117,11,0,0,0,115,117,102, + 102,105,120,95,116,121,112,101,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 10,0,0,0,60,108,105,115,116,99,111,109,112,62,21,1, + 0,0,115,4,0,0,0,9,0,3,1,117,32,0,0,0, + 95,115,117,102,102,105,120,95,108,105,115,116,46,60,108,111, + 99,97,108,115,62,46,60,108,105,115,116,99,111,109,112,62, + 40,2,0,0,0,117,4,0,0,0,95,105,109,112,117,12, + 0,0,0,103,101,116,95,115,117,102,102,105,120,101,115,40, + 1,0,0,0,117,11,0,0,0,115,117,102,102,105,120,95, + 116,121,112,101,40,0,0,0,0,40,1,0,0,0,117,11, + 0,0,0,115,117,102,102,105,120,95,116,121,112,101,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,12,0,0,0,95,115,117,102,102,105,120,95,108,105,115, + 116,19,1,0,0,115,2,0,0,0,0,2,117,12,0,0, + 0,95,115,117,102,102,105,120,95,108,105,115,116,99,1,0, + 0,0,0,0,0,0,1,0,0,0,6,0,0,0,66,0, + 0,0,115,155,0,0,0,124,0,0,69,101,0,0,90,1, + 0,100,0,0,90,2,0,100,1,0,90,3,0,101,4,0, + 100,12,0,100,2,0,100,3,0,132,1,0,131,1,0,90, + 6,0,101,4,0,101,7,0,101,8,0,101,9,0,100,4, + 0,100,5,0,132,0,0,131,1,0,131,1,0,131,1,0, + 131,1,0,90,10,0,101,4,0,101,9,0,100,6,0,100, + 7,0,132,0,0,131,1,0,131,1,0,90,11,0,101,4, + 0,101,9,0,100,8,0,100,9,0,132,0,0,131,1,0, + 131,1,0,90,12,0,101,4,0,101,9,0,100,10,0,100, + 11,0,132,0,0,131,1,0,131,1,0,90,13,0,100,12, + 0,83,40,13,0,0,0,117,15,0,0,0,66,117,105,108, + 116,105,110,73,109,112,111,114,116,101,114,117,144,0,0,0, + 77,101,116,97,32,112,97,116,104,32,105,109,112,111,114,116, + 32,102,111,114,32,98,117,105,108,116,45,105,110,32,109,111, + 100,117,108,101,115,46,10,10,32,32,32,32,65,108,108,32, + 109,101,116,104,111,100,115,32,97,114,101,32,101,105,116,104, + 101,114,32,99,108,97,115,115,32,111,114,32,115,116,97,116, + 105,99,32,109,101,116,104,111,100,115,32,116,111,32,97,118, + 111,105,100,32,116,104,101,32,110,101,101,100,32,116,111,10, + 32,32,32,32,105,110,115,116,97,110,116,105,97,116,101,32, + 116,104,101,32,99,108,97,115,115,46,10,10,32,32,32,32, + 99,3,0,0,0,0,0,0,0,3,0,0,0,2,0,0, + 0,67,0,0,0,115,39,0,0,0,124,2,0,100,1,0, + 107,9,0,114,16,0,100,1,0,83,116,1,0,106,2,0, + 124,1,0,131,1,0,114,35,0,124,0,0,83,100,1,0, + 83,40,2,0,0,0,117,113,0,0,0,70,105,110,100,32, + 116,104,101,32,98,117,105,108,116,45,105,110,32,109,111,100, + 117,108,101,46,10,10,32,32,32,32,32,32,32,32,73,102, + 32,39,112,97,116,104,39,32,105,115,32,101,118,101,114,32, + 115,112,101,99,105,102,105,101,100,32,116,104,101,110,32,116, + 104,101,32,115,101,97,114,99,104,32,105,115,32,99,111,110, + 115,105,100,101,114,101,100,32,97,32,102,97,105,108,117,114, + 101,46,10,10,32,32,32,32,32,32,32,32,78,40,3,0, + 0,0,117,4,0,0,0,78,111,110,101,117,4,0,0,0, + 95,105,109,112,117,10,0,0,0,105,115,95,98,117,105,108, + 116,105,110,40,3,0,0,0,117,3,0,0,0,99,108,115, + 117,8,0,0,0,102,117,108,108,110,97,109,101,117,4,0, + 0,0,112,97,116,104,40,0,0,0,0,40,0,0,0,0, 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,17,0,0,0,95,114,101,113,117,105,114,101,115, - 95,98,117,105,108,116,105,110,253,0,0,0,115,6,0,0, - 0,0,2,18,5,13,1,117,17,0,0,0,95,114,101,113, - 117,105,114,101,115,95,98,117,105,108,116,105,110,99,1,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, - 0,0,115,35,0,0,0,135,0,0,102,1,0,100,1,0, - 100,2,0,134,0,0,125,1,0,116,0,0,124,1,0,136, - 0,0,131,2,0,1,124,1,0,83,40,3,0,0,0,117, - 47,0,0,0,68,101,99,111,114,97,116,111,114,32,116,111, - 32,118,101,114,105,102,121,32,116,104,101,32,110,97,109,101, - 100,32,109,111,100,117,108,101,32,105,115,32,102,114,111,122, - 101,110,46,99,2,0,0,0,0,0,0,0,2,0,0,0, - 4,0,0,0,19,0,0,0,115,58,0,0,0,116,0,0, - 106,1,0,124,1,0,131,1,0,115,45,0,116,2,0,100, - 1,0,106,3,0,124,1,0,131,1,0,100,2,0,124,1, - 0,131,1,1,130,1,0,110,0,0,136,0,0,124,0,0, - 124,1,0,131,2,0,83,40,3,0,0,0,78,117,26,0, - 0,0,123,48,125,32,105,115,32,110,111,116,32,97,32,102, - 114,111,122,101,110,32,109,111,100,117,108,101,117,4,0,0, - 0,110,97,109,101,40,4,0,0,0,117,4,0,0,0,95, - 105,109,112,117,9,0,0,0,105,115,95,102,114,111,122,101, - 110,117,11,0,0,0,73,109,112,111,114,116,69,114,114,111, - 114,117,6,0,0,0,102,111,114,109,97,116,40,2,0,0, - 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,102, - 117,108,108,110,97,109,101,40,1,0,0,0,117,3,0,0, - 0,102,120,110,40,0,0,0,0,117,29,0,0,0,60,102, + 112,62,117,11,0,0,0,102,105,110,100,95,109,111,100,117, + 108,101,36,1,0,0,115,6,0,0,0,0,7,12,1,4, + 1,117,27,0,0,0,66,117,105,108,116,105,110,73,109,112, + 111,114,116,101,114,46,102,105,110,100,95,109,111,100,117,108, + 101,99,2,0,0,0,0,0,0,0,3,0,0,0,9,0, + 0,0,67,0,0,0,115,85,0,0,0,124,1,0,116,0, + 0,106,1,0,107,6,0,125,2,0,121,17,0,116,2,0, + 106,3,0,124,1,0,131,1,0,83,87,110,46,0,1,1, + 1,124,2,0,12,114,73,0,124,1,0,116,0,0,106,1, + 0,107,6,0,114,73,0,116,0,0,106,1,0,124,1,0, + 61,110,0,0,130,0,0,89,110,1,0,88,100,1,0,83, + 40,2,0,0,0,117,23,0,0,0,76,111,97,100,32,97, + 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, + 46,78,40,4,0,0,0,117,3,0,0,0,115,121,115,117, + 7,0,0,0,109,111,100,117,108,101,115,117,4,0,0,0, + 95,105,109,112,117,12,0,0,0,105,110,105,116,95,98,117, + 105,108,116,105,110,40,3,0,0,0,117,3,0,0,0,99, + 108,115,117,8,0,0,0,102,117,108,108,110,97,109,101,117, + 9,0,0,0,105,115,95,114,101,108,111,97,100,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,11,0,0,0,108,111, + 97,100,95,109,111,100,117,108,101,47,1,0,0,115,14,0, + 0,0,0,6,15,1,3,1,17,1,3,1,22,1,13,1, + 117,27,0,0,0,66,117,105,108,116,105,110,73,109,112,111, + 114,116,101,114,46,108,111,97,100,95,109,111,100,117,108,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,115,4,0,0,0,100,1,0,83,40,2, + 0,0,0,117,57,0,0,0,82,101,116,117,114,110,32,78, + 111,110,101,32,97,115,32,98,117,105,108,116,45,105,110,32, + 109,111,100,117,108,101,115,32,100,111,32,110,111,116,32,104, + 97,118,101,32,99,111,100,101,32,111,98,106,101,99,116,115, + 46,78,40,1,0,0,0,117,4,0,0,0,78,111,110,101, + 40,2,0,0,0,117,3,0,0,0,99,108,115,117,8,0, + 0,0,102,117,108,108,110,97,109,101,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,8,0,0,0,103,101,116,95,99, + 111,100,101,61,1,0,0,115,2,0,0,0,0,4,117,24, + 0,0,0,66,117,105,108,116,105,110,73,109,112,111,114,116, + 101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,0,83,40,2,0,0,0,117,56, + 0,0,0,82,101,116,117,114,110,32,78,111,110,101,32,97, + 115,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, + 101,115,32,100,111,32,110,111,116,32,104,97,118,101,32,115, + 111,117,114,99,101,32,99,111,100,101,46,78,40,1,0,0, + 0,117,4,0,0,0,78,111,110,101,40,2,0,0,0,117, + 3,0,0,0,99,108,115,117,8,0,0,0,102,117,108,108, + 110,97,109,101,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,10,0,0,0,103,101,116,95,115,111,117,114,99,101,67, + 1,0,0,115,2,0,0,0,0,4,117,26,0,0,0,66, + 117,105,108,116,105,110,73,109,112,111,114,116,101,114,46,103, + 101,116,95,115,111,117,114,99,101,99,2,0,0,0,0,0, + 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, + 0,0,0,100,1,0,83,40,2,0,0,0,117,51,0,0, + 0,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, + 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,115, + 32,97,114,101,32,110,101,118,101,114,32,112,97,99,107,97, + 103,101,115,46,70,40,1,0,0,0,117,5,0,0,0,70, + 97,108,115,101,40,2,0,0,0,117,3,0,0,0,99,108, + 115,117,8,0,0,0,102,117,108,108,110,97,109,101,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,105, + 115,95,112,97,99,107,97,103,101,73,1,0,0,115,2,0, + 0,0,0,4,117,26,0,0,0,66,117,105,108,116,105,110, + 73,109,112,111,114,116,101,114,46,105,115,95,112,97,99,107, + 97,103,101,78,40,14,0,0,0,117,8,0,0,0,95,95, + 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, + 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, + 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, + 95,95,117,11,0,0,0,99,108,97,115,115,109,101,116,104, + 111,100,117,4,0,0,0,78,111,110,101,117,11,0,0,0, + 102,105,110,100,95,109,111,100,117,108,101,117,11,0,0,0, + 115,101,116,95,112,97,99,107,97,103,101,117,10,0,0,0, + 115,101,116,95,108,111,97,100,101,114,117,17,0,0,0,95, + 114,101,113,117,105,114,101,115,95,98,117,105,108,116,105,110, + 117,11,0,0,0,108,111,97,100,95,109,111,100,117,108,101, + 117,8,0,0,0,103,101,116,95,99,111,100,101,117,10,0, + 0,0,103,101,116,95,115,111,117,114,99,101,117,10,0,0, + 0,105,115,95,112,97,99,107,97,103,101,40,1,0,0,0, + 117,10,0,0,0,95,95,108,111,99,97,108,115,95,95,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,24,0,0,0, - 95,114,101,113,117,105,114,101,115,95,102,114,111,122,101,110, - 95,119,114,97,112,112,101,114,10,1,0,0,115,8,0,0, - 0,0,1,15,1,18,1,12,1,117,50,0,0,0,95,114, - 101,113,117,105,114,101,115,95,102,114,111,122,101,110,46,60, - 108,111,99,97,108,115,62,46,95,114,101,113,117,105,114,101, - 115,95,102,114,111,122,101,110,95,119,114,97,112,112,101,114, - 40,1,0,0,0,117,5,0,0,0,95,119,114,97,112,40, - 2,0,0,0,117,3,0,0,0,102,120,110,117,24,0,0, - 0,95,114,101,113,117,105,114,101,115,95,102,114,111,122,101, - 110,95,119,114,97,112,112,101,114,40,0,0,0,0,40,1, - 0,0,0,117,3,0,0,0,102,120,110,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,16,0, - 0,0,95,114,101,113,117,105,114,101,115,95,102,114,111,122, - 101,110,8,1,0,0,115,6,0,0,0,0,2,18,5,13, - 1,117,16,0,0,0,95,114,101,113,117,105,114,101,115,95, - 102,114,111,122,101,110,99,1,0,0,0,0,0,0,0,1, - 0,0,0,3,0,0,0,3,0,0,0,115,29,0,0,0, - 135,0,0,102,1,0,100,1,0,100,2,0,134,0,0,116, - 0,0,106,1,0,131,0,0,68,131,1,0,83,40,3,0, - 0,0,117,58,0,0,0,82,101,116,117,114,110,32,97,32, - 108,105,115,116,32,111,102,32,102,105,108,101,32,115,117,102, - 102,105,120,101,115,32,98,97,115,101,100,32,111,110,32,116, - 104,101,32,105,109,112,32,102,105,108,101,32,116,121,112,101, - 46,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,19,0,0,0,115,42,0,0,0,103,0,0,124,0, - 0,93,32,0,125,1,0,124,1,0,100,0,0,25,136,0, - 0,107,2,0,114,6,0,124,1,0,100,1,0,25,145,2, - 0,113,6,0,83,40,2,0,0,0,105,2,0,0,0,105, - 0,0,0,0,40,0,0,0,0,40,2,0,0,0,117,2, - 0,0,0,46,48,117,6,0,0,0,115,117,102,102,105,120, - 40,1,0,0,0,117,11,0,0,0,115,117,102,102,105,120, - 95,116,121,112,101,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, - 0,60,108,105,115,116,99,111,109,112,62,21,1,0,0,115, - 4,0,0,0,9,0,3,1,117,32,0,0,0,95,115,117, - 102,102,105,120,95,108,105,115,116,46,60,108,111,99,97,108, - 115,62,46,60,108,105,115,116,99,111,109,112,62,40,2,0, - 0,0,117,4,0,0,0,95,105,109,112,117,12,0,0,0, - 103,101,116,95,115,117,102,102,105,120,101,115,40,1,0,0, - 0,117,11,0,0,0,115,117,102,102,105,120,95,116,121,112, - 101,40,0,0,0,0,40,1,0,0,0,117,11,0,0,0, - 115,117,102,102,105,120,95,116,121,112,101,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,12,0, - 0,0,95,115,117,102,102,105,120,95,108,105,115,116,19,1, - 0,0,115,2,0,0,0,0,2,117,12,0,0,0,95,115, - 117,102,102,105,120,95,108,105,115,116,99,1,0,0,0,0, - 0,0,0,1,0,0,0,6,0,0,0,66,0,0,0,115, - 155,0,0,0,124,0,0,69,101,0,0,90,1,0,100,0, - 0,90,2,0,100,1,0,90,3,0,101,4,0,100,12,0, - 100,2,0,100,3,0,132,1,0,131,1,0,90,6,0,101, - 4,0,101,7,0,101,8,0,101,9,0,100,4,0,100,5, - 0,132,0,0,131,1,0,131,1,0,131,1,0,131,1,0, - 90,10,0,101,4,0,101,9,0,100,6,0,100,7,0,132, - 0,0,131,1,0,131,1,0,90,11,0,101,4,0,101,9, - 0,100,8,0,100,9,0,132,0,0,131,1,0,131,1,0, - 90,12,0,101,4,0,101,9,0,100,10,0,100,11,0,132, - 0,0,131,1,0,131,1,0,90,13,0,100,12,0,83,40, - 13,0,0,0,117,15,0,0,0,66,117,105,108,116,105,110, - 73,109,112,111,114,116,101,114,117,144,0,0,0,77,101,116, - 97,32,112,97,116,104,32,105,109,112,111,114,116,32,102,111, - 114,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, - 101,115,46,10,10,32,32,32,32,65,108,108,32,109,101,116, - 104,111,100,115,32,97,114,101,32,101,105,116,104,101,114,32, - 99,108,97,115,115,32,111,114,32,115,116,97,116,105,99,32, - 109,101,116,104,111,100,115,32,116,111,32,97,118,111,105,100, - 32,116,104,101,32,110,101,101,100,32,116,111,10,32,32,32, - 32,105,110,115,116,97,110,116,105,97,116,101,32,116,104,101, - 32,99,108,97,115,115,46,10,10,32,32,32,32,99,3,0, - 0,0,0,0,0,0,3,0,0,0,2,0,0,0,67,0, - 0,0,115,39,0,0,0,124,2,0,100,1,0,107,9,0, - 114,16,0,100,1,0,83,116,1,0,106,2,0,124,1,0, - 131,1,0,114,35,0,124,0,0,83,100,1,0,83,40,2, - 0,0,0,117,113,0,0,0,70,105,110,100,32,116,104,101, - 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, - 46,10,10,32,32,32,32,32,32,32,32,73,102,32,39,112, - 97,116,104,39,32,105,115,32,101,118,101,114,32,115,112,101, - 99,105,102,105,101,100,32,116,104,101,110,32,116,104,101,32, - 115,101,97,114,99,104,32,105,115,32,99,111,110,115,105,100, - 101,114,101,100,32,97,32,102,97,105,108,117,114,101,46,10, - 10,32,32,32,32,32,32,32,32,78,40,3,0,0,0,117, - 4,0,0,0,78,111,110,101,117,4,0,0,0,95,105,109, - 112,117,10,0,0,0,105,115,95,98,117,105,108,116,105,110, - 40,3,0,0,0,117,3,0,0,0,99,108,115,117,8,0, - 0,0,102,117,108,108,110,97,109,101,117,4,0,0,0,112, - 97,116,104,40,0,0,0,0,40,0,0,0,0,117,29,0, + 95,98,111,111,116,115,116,114,97,112,62,117,15,0,0,0, + 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,27, + 1,0,0,115,26,0,0,0,16,7,6,2,3,1,18,10, + 3,1,3,1,3,1,27,11,3,1,21,5,3,1,21,5, + 3,1,117,15,0,0,0,66,117,105,108,116,105,110,73,109, + 112,111,114,116,101,114,99,1,0,0,0,0,0,0,0,1, + 0,0,0,6,0,0,0,66,0,0,0,115,155,0,0,0, + 124,0,0,69,101,0,0,90,1,0,100,0,0,90,2,0, + 100,1,0,90,3,0,101,4,0,100,12,0,100,2,0,100, + 3,0,132,1,0,131,1,0,90,6,0,101,4,0,101,7, + 0,101,8,0,101,9,0,100,4,0,100,5,0,132,0,0, + 131,1,0,131,1,0,131,1,0,131,1,0,90,10,0,101, + 4,0,101,9,0,100,6,0,100,7,0,132,0,0,131,1, + 0,131,1,0,90,11,0,101,4,0,101,9,0,100,8,0, + 100,9,0,132,0,0,131,1,0,131,1,0,90,12,0,101, + 4,0,101,9,0,100,10,0,100,11,0,132,0,0,131,1, + 0,131,1,0,90,13,0,100,12,0,83,40,13,0,0,0, + 117,14,0,0,0,70,114,111,122,101,110,73,109,112,111,114, + 116,101,114,117,142,0,0,0,77,101,116,97,32,112,97,116, + 104,32,105,109,112,111,114,116,32,102,111,114,32,102,114,111, + 122,101,110,32,109,111,100,117,108,101,115,46,10,10,32,32, + 32,32,65,108,108,32,109,101,116,104,111,100,115,32,97,114, + 101,32,101,105,116,104,101,114,32,99,108,97,115,115,32,111, + 114,32,115,116,97,116,105,99,32,109,101,116,104,111,100,115, + 32,116,111,32,97,118,111,105,100,32,116,104,101,32,110,101, + 101,100,32,116,111,10,32,32,32,32,105,110,115,116,97,110, + 116,105,97,116,101,32,116,104,101,32,99,108,97,115,115,46, + 10,10,32,32,32,32,99,3,0,0,0,0,0,0,0,3, + 0,0,0,2,0,0,0,67,0,0,0,115,23,0,0,0, + 116,0,0,106,1,0,124,1,0,131,1,0,114,19,0,124, + 0,0,83,100,1,0,83,40,2,0,0,0,117,21,0,0, + 0,70,105,110,100,32,97,32,102,114,111,122,101,110,32,109, + 111,100,117,108,101,46,78,40,3,0,0,0,117,4,0,0, + 0,95,105,109,112,117,9,0,0,0,105,115,95,102,114,111, + 122,101,110,117,4,0,0,0,78,111,110,101,40,3,0,0, + 0,117,3,0,0,0,99,108,115,117,8,0,0,0,102,117, + 108,108,110,97,109,101,117,4,0,0,0,112,97,116,104,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, + 102,105,110,100,95,109,111,100,117,108,101,89,1,0,0,115, + 2,0,0,0,0,3,117,26,0,0,0,70,114,111,122,101, + 110,73,109,112,111,114,116,101,114,46,102,105,110,100,95,109, + 111,100,117,108,101,99,2,0,0,0,0,0,0,0,3,0, + 0,0,9,0,0,0,67,0,0,0,115,85,0,0,0,124, + 1,0,116,0,0,106,1,0,107,6,0,125,2,0,121,17, + 0,116,2,0,106,3,0,124,1,0,131,1,0,83,87,110, + 46,0,1,1,1,124,2,0,12,114,73,0,124,1,0,116, + 0,0,106,1,0,107,6,0,114,73,0,116,0,0,106,1, + 0,124,1,0,61,110,0,0,130,0,0,89,110,1,0,88, + 100,1,0,83,40,2,0,0,0,117,21,0,0,0,76,111, + 97,100,32,97,32,102,114,111,122,101,110,32,109,111,100,117, + 108,101,46,78,40,4,0,0,0,117,3,0,0,0,115,121, + 115,117,7,0,0,0,109,111,100,117,108,101,115,117,4,0, + 0,0,95,105,109,112,117,11,0,0,0,105,110,105,116,95, + 102,114,111,122,101,110,40,3,0,0,0,117,3,0,0,0, + 99,108,115,117,8,0,0,0,102,117,108,108,110,97,109,101, + 117,9,0,0,0,105,115,95,114,101,108,111,97,100,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,11,0,0,0,108, + 111,97,100,95,109,111,100,117,108,101,94,1,0,0,115,14, + 0,0,0,0,6,15,1,3,1,17,1,3,1,22,1,13, + 1,117,26,0,0,0,70,114,111,122,101,110,73,109,112,111, + 114,116,101,114,46,108,111,97,100,95,109,111,100,117,108,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, + 0,67,0,0,0,115,13,0,0,0,116,0,0,106,1,0, + 124,1,0,131,1,0,83,40,1,0,0,0,117,45,0,0, + 0,82,101,116,117,114,110,32,116,104,101,32,99,111,100,101, + 32,111,98,106,101,99,116,32,102,111,114,32,116,104,101,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,46,40,2, + 0,0,0,117,4,0,0,0,95,105,109,112,117,17,0,0, + 0,103,101,116,95,102,114,111,122,101,110,95,111,98,106,101, + 99,116,40,2,0,0,0,117,3,0,0,0,99,108,115,117, + 8,0,0,0,102,117,108,108,110,97,109,101,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,8,0,0,0,103,101,116, + 95,99,111,100,101,108,1,0,0,115,2,0,0,0,0,4, + 117,23,0,0,0,70,114,111,122,101,110,73,109,112,111,114, + 116,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,0,83,40,2,0,0,0,117, + 54,0,0,0,82,101,116,117,114,110,32,78,111,110,101,32, + 97,115,32,102,114,111,122,101,110,32,109,111,100,117,108,101, + 115,32,100,111,32,110,111,116,32,104,97,118,101,32,115,111, + 117,114,99,101,32,99,111,100,101,46,78,40,1,0,0,0, + 117,4,0,0,0,78,111,110,101,40,2,0,0,0,117,3, + 0,0,0,99,108,115,117,8,0,0,0,102,117,108,108,110, + 97,109,101,40,0,0,0,0,40,0,0,0,0,117,29,0, 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 11,0,0,0,102,105,110,100,95,109,111,100,117,108,101,36, - 1,0,0,115,6,0,0,0,0,7,12,1,4,1,117,27, - 0,0,0,66,117,105,108,116,105,110,73,109,112,111,114,116, - 101,114,46,102,105,110,100,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,3,0,0,0,9,0,0,0,67, - 0,0,0,115,85,0,0,0,124,1,0,116,0,0,106,1, - 0,107,6,0,125,2,0,121,17,0,116,2,0,106,3,0, - 124,1,0,131,1,0,83,87,110,46,0,1,1,1,124,2, - 0,12,114,73,0,124,1,0,116,0,0,106,1,0,107,6, - 0,114,73,0,116,0,0,106,1,0,124,1,0,61,110,0, - 0,130,0,0,89,110,1,0,88,100,1,0,83,40,2,0, - 0,0,117,23,0,0,0,76,111,97,100,32,97,32,98,117, - 105,108,116,45,105,110,32,109,111,100,117,108,101,46,78,40, - 4,0,0,0,117,3,0,0,0,115,121,115,117,7,0,0, - 0,109,111,100,117,108,101,115,117,4,0,0,0,95,105,109, - 112,117,12,0,0,0,105,110,105,116,95,98,117,105,108,116, - 105,110,40,3,0,0,0,117,3,0,0,0,99,108,115,117, - 8,0,0,0,102,117,108,108,110,97,109,101,117,9,0,0, - 0,105,115,95,114,101,108,111,97,100,40,0,0,0,0,40, + 10,0,0,0,103,101,116,95,115,111,117,114,99,101,114,1, + 0,0,115,2,0,0,0,0,4,117,25,0,0,0,70,114, + 111,122,101,110,73,109,112,111,114,116,101,114,46,103,101,116, + 95,115,111,117,114,99,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,2,0,0,0,67,0,0,0,115,13,0,0, + 0,116,0,0,106,1,0,124,1,0,131,1,0,83,40,1, + 0,0,0,117,41,0,0,0,82,101,116,117,114,110,32,105, + 102,32,116,104,101,32,102,114,111,122,101,110,32,109,111,100, + 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, + 46,40,2,0,0,0,117,4,0,0,0,95,105,109,112,117, + 17,0,0,0,105,115,95,102,114,111,122,101,110,95,112,97, + 99,107,97,103,101,40,2,0,0,0,117,3,0,0,0,99, + 108,115,117,8,0,0,0,102,117,108,108,110,97,109,101,40, + 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, + 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, + 95,98,111,111,116,115,116,114,97,112,62,117,10,0,0,0, + 105,115,95,112,97,99,107,97,103,101,120,1,0,0,115,2, + 0,0,0,0,4,117,25,0,0,0,70,114,111,122,101,110, + 73,109,112,111,114,116,101,114,46,105,115,95,112,97,99,107, + 97,103,101,78,40,14,0,0,0,117,8,0,0,0,95,95, + 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, + 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, + 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, + 95,95,117,11,0,0,0,99,108,97,115,115,109,101,116,104, + 111,100,117,4,0,0,0,78,111,110,101,117,11,0,0,0, + 102,105,110,100,95,109,111,100,117,108,101,117,11,0,0,0, + 115,101,116,95,112,97,99,107,97,103,101,117,10,0,0,0, + 115,101,116,95,108,111,97,100,101,114,117,16,0,0,0,95, + 114,101,113,117,105,114,101,115,95,102,114,111,122,101,110,117, + 11,0,0,0,108,111,97,100,95,109,111,100,117,108,101,117, + 8,0,0,0,103,101,116,95,99,111,100,101,117,10,0,0, + 0,103,101,116,95,115,111,117,114,99,101,117,10,0,0,0, + 105,115,95,112,97,99,107,97,103,101,40,1,0,0,0,117, + 10,0,0,0,95,95,108,111,99,97,108,115,95,95,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,14,0,0,0,70, + 114,111,122,101,110,73,109,112,111,114,116,101,114,80,1,0, + 0,115,26,0,0,0,16,7,6,2,3,1,18,4,3,1, + 3,1,3,1,27,11,3,1,21,5,3,1,21,5,3,1, + 117,14,0,0,0,70,114,111,122,101,110,73,109,112,111,114, + 116,101,114,99,1,0,0,0,0,0,0,0,1,0,0,0, + 5,0,0,0,66,0,0,0,115,74,0,0,0,124,0,0, + 69,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, + 90,3,0,100,2,0,100,3,0,132,0,0,90,4,0,100, + 4,0,100,5,0,132,0,0,90,5,0,101,6,0,100,6, + 0,100,10,0,100,7,0,100,8,0,132,0,1,131,1,0, + 90,8,0,100,9,0,83,40,11,0,0,0,117,13,0,0, + 0,95,76,111,97,100,101,114,66,97,115,105,99,115,117,84, + 0,0,0,66,97,115,101,32,99,108,97,115,115,32,111,102, + 32,99,111,109,109,111,110,32,99,111,100,101,32,110,101,101, + 100,101,100,32,98,121,32,98,111,116,104,32,83,111,117,114, + 99,101,76,111,97,100,101,114,32,97,110,100,10,32,32,32, + 32,95,83,111,117,114,99,101,108,101,115,115,70,105,108,101, + 76,111,97,100,101,114,46,99,2,0,0,0,0,0,0,0, + 3,0,0,0,3,0,0,0,67,0,0,0,115,54,0,0, + 0,124,0,0,106,0,0,124,1,0,131,1,0,106,1,0, + 116,2,0,131,1,0,100,1,0,25,125,2,0,124,2,0, + 106,3,0,100,2,0,100,3,0,131,2,0,100,4,0,25, + 100,5,0,107,2,0,83,40,6,0,0,0,117,141,0,0, + 0,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,111,102,32,73,110,115,112, + 101,99,116,76,111,97,100,101,114,46,105,115,95,112,97,99, + 107,97,103,101,32,98,121,32,99,104,101,99,107,105,110,103, + 32,105,102,10,32,32,32,32,32,32,32,32,116,104,101,32, + 112,97,116,104,32,114,101,116,117,114,110,101,100,32,98,121, + 32,103,101,116,95,102,105,108,101,110,97,109,101,32,104,97, + 115,32,97,32,102,105,108,101,110,97,109,101,32,111,102,32, + 39,95,95,105,110,105,116,95,95,46,112,121,39,46,105,2, + 0,0,0,117,1,0,0,0,46,105,1,0,0,0,105,0, + 0,0,0,117,8,0,0,0,95,95,105,110,105,116,95,95, + 40,4,0,0,0,117,12,0,0,0,103,101,116,95,102,105, + 108,101,110,97,109,101,117,10,0,0,0,114,112,97,114,116, + 105,116,105,111,110,117,8,0,0,0,112,97,116,104,95,115, + 101,112,117,6,0,0,0,114,115,112,108,105,116,40,3,0, + 0,0,117,4,0,0,0,115,101,108,102,117,8,0,0,0, + 102,117,108,108,110,97,109,101,117,8,0,0,0,102,105,108, + 101,110,97,109,101,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,10,0,0,0,105,115,95,112,97,99,107,97,103,101, + 132,1,0,0,115,4,0,0,0,0,3,28,1,117,24,0, + 0,0,95,76,111,97,100,101,114,66,97,115,105,99,115,46, + 105,115,95,112,97,99,107,97,103,101,99,5,0,0,0,0, + 0,0,0,11,0,0,0,23,0,0,0,67,0,0,0,115, + 213,1,0,0,124,2,0,100,1,0,100,2,0,133,2,0, + 25,125,5,0,124,2,0,100,2,0,100,3,0,133,2,0, + 25,125,6,0,124,2,0,100,3,0,100,4,0,133,2,0, + 25,125,7,0,116,0,0,124,5,0,131,1,0,100,2,0, + 107,3,0,115,84,0,124,5,0,116,1,0,106,2,0,131, + 0,0,107,3,0,114,120,0,116,3,0,100,5,0,106,4, + 0,124,1,0,131,1,0,100,6,0,124,1,0,100,7,0, + 124,3,0,131,1,2,130,1,0,110,116,0,116,0,0,124, + 6,0,131,1,0,100,2,0,107,3,0,114,178,0,100,8, + 0,106,4,0,124,1,0,131,1,0,125,8,0,116,5,0, + 124,8,0,131,1,0,1,116,6,0,124,8,0,131,1,0, + 130,1,0,110,58,0,116,0,0,124,7,0,131,1,0,100, + 2,0,107,3,0,114,236,0,100,9,0,106,4,0,124,1, + 0,131,1,0,125,8,0,116,5,0,124,8,0,131,1,0, + 1,116,6,0,124,8,0,131,1,0,130,1,0,110,0,0, + 124,4,0,100,1,0,107,9,0,114,199,1,121,20,0,116, + 8,0,124,4,0,100,10,0,25,131,1,0,125,9,0,87, + 110,18,0,4,116,9,0,107,10,0,114,32,1,1,1,1, + 89,110,71,0,88,116,10,0,124,6,0,131,1,0,124,9, + 0,107,3,0,114,103,1,100,11,0,106,4,0,124,1,0, + 131,1,0,125,8,0,116,5,0,124,8,0,131,1,0,1, + 116,3,0,124,8,0,100,6,0,124,1,0,100,7,0,124, + 3,0,131,1,2,130,1,0,110,0,0,121,18,0,124,4, + 0,100,12,0,25,100,13,0,64,125,10,0,87,110,18,0, + 4,116,9,0,107,10,0,114,141,1,1,1,1,89,113,199, + 1,88,116,10,0,124,7,0,131,1,0,124,10,0,107,3, + 0,114,199,1,116,3,0,100,11,0,106,4,0,124,1,0, + 131,1,0,100,6,0,124,1,0,100,7,0,124,3,0,131, + 1,2,130,1,0,113,199,1,110,0,0,124,2,0,100,4, + 0,100,1,0,133,2,0,25,83,40,14,0,0,0,117,193, + 0,0,0,82,101,116,117,114,110,32,116,104,101,32,109,97, + 114,115,104,97,108,108,101,100,32,98,121,116,101,115,32,102, + 114,111,109,32,98,121,116,101,99,111,100,101,44,32,118,101, + 114,105,102,121,105,110,103,32,116,104,101,32,109,97,103,105, + 99,10,32,32,32,32,32,32,32,32,110,117,109,98,101,114, + 44,32,116,105,109,101,115,116,97,109,112,32,97,110,100,32, + 115,111,117,114,99,101,32,115,105,122,101,32,97,108,111,110, + 103,32,116,104,101,32,119,97,121,46,10,10,32,32,32,32, + 32,32,32,32,73,102,32,115,111,117,114,99,101,95,115,116, + 97,116,115,32,105,115,32,78,111,110,101,32,116,104,101,110, + 32,115,107,105,112,32,116,104,101,32,116,105,109,101,115,116, + 97,109,112,32,99,104,101,99,107,46,10,10,32,32,32,32, + 32,32,32,32,78,105,4,0,0,0,105,8,0,0,0,105, + 12,0,0,0,117,22,0,0,0,98,97,100,32,109,97,103, + 105,99,32,110,117,109,98,101,114,32,105,110,32,123,125,117, + 4,0,0,0,110,97,109,101,117,4,0,0,0,112,97,116, + 104,117,19,0,0,0,98,97,100,32,116,105,109,101,115,116, + 97,109,112,32,105,110,32,123,125,117,14,0,0,0,98,97, + 100,32,115,105,122,101,32,105,110,32,123,125,117,5,0,0, + 0,109,116,105,109,101,117,24,0,0,0,98,121,116,101,99, + 111,100,101,32,105,115,32,115,116,97,108,101,32,102,111,114, + 32,123,125,117,4,0,0,0,115,105,122,101,73,255,255,255, + 255,0,0,0,0,40,11,0,0,0,117,3,0,0,0,108, + 101,110,117,4,0,0,0,95,105,109,112,117,9,0,0,0, + 103,101,116,95,109,97,103,105,99,117,11,0,0,0,73,109, + 112,111,114,116,69,114,114,111,114,117,6,0,0,0,102,111, + 114,109,97,116,117,15,0,0,0,118,101,114,98,111,115,101, + 95,109,101,115,115,97,103,101,117,8,0,0,0,69,79,70, + 69,114,114,111,114,117,4,0,0,0,78,111,110,101,117,3, + 0,0,0,105,110,116,117,8,0,0,0,75,101,121,69,114, + 114,111,114,117,7,0,0,0,95,114,95,108,111,110,103,40, + 11,0,0,0,117,4,0,0,0,115,101,108,102,117,8,0, + 0,0,102,117,108,108,110,97,109,101,117,4,0,0,0,100, + 97,116,97,117,13,0,0,0,98,121,116,101,99,111,100,101, + 95,112,97,116,104,117,12,0,0,0,115,111,117,114,99,101, + 95,115,116,97,116,115,117,5,0,0,0,109,97,103,105,99, + 117,13,0,0,0,114,97,119,95,116,105,109,101,115,116,97, + 109,112,117,8,0,0,0,114,97,119,95,115,105,122,101,117, + 7,0,0,0,109,101,115,115,97,103,101,117,12,0,0,0, + 115,111,117,114,99,101,95,109,116,105,109,101,117,11,0,0, + 0,115,111,117,114,99,101,95,115,105,122,101,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,20,0,0,0,95,98,121, + 116,101,115,95,102,114,111,109,95,98,121,116,101,99,111,100, + 101,138,1,0,0,115,66,0,0,0,0,7,16,1,16,1, + 16,1,36,1,18,1,18,1,18,1,15,1,10,1,15,1, + 18,1,15,1,10,1,15,1,12,1,3,1,20,1,13,1, + 5,2,18,1,15,1,10,1,15,1,12,1,3,1,18,1, + 13,1,5,2,18,1,3,1,15,1,21,3,117,34,0,0, + 0,95,76,111,97,100,101,114,66,97,115,105,99,115,46,95, + 98,121,116,101,115,95,102,114,111,109,95,98,121,116,101,99, + 111,100,101,117,10,0,0,0,115,111,117,114,99,101,108,101, + 115,115,99,2,0,0,0,1,0,0,0,5,0,0,0,3, + 0,0,0,67,0,0,0,115,196,0,0,0,124,1,0,106, + 0,0,125,3,0,124,0,0,106,1,0,124,3,0,131,1, + 0,125,4,0,124,0,0,106,2,0,124,3,0,131,1,0, + 124,1,0,95,3,0,124,2,0,115,72,0,116,4,0,106, + 5,0,124,1,0,106,3,0,131,1,0,124,1,0,95,6, + 0,110,12,0,124,1,0,106,3,0,124,1,0,95,6,0, + 124,3,0,124,1,0,95,7,0,124,0,0,106,8,0,124, + 3,0,131,1,0,114,142,0,124,1,0,106,3,0,106,9, + 0,116,10,0,100,1,0,131,2,0,100,2,0,25,103,1, + 0,124,1,0,95,11,0,110,25,0,124,1,0,106,7,0, + 106,12,0,100,3,0,131,1,0,100,2,0,25,124,1,0, + 95,7,0,124,0,0,124,1,0,95,13,0,116,14,0,124, + 4,0,124,1,0,106,15,0,131,2,0,1,124,1,0,83, + 40,4,0,0,0,117,82,0,0,0,72,101,108,112,101,114, + 32,102,111,114,32,108,111,97,100,95,109,111,100,117,108,101, + 32,97,98,108,101,32,116,111,32,104,97,110,100,108,101,32, + 101,105,116,104,101,114,32,115,111,117,114,99,101,32,111,114, + 32,115,111,117,114,99,101,108,101,115,115,10,32,32,32,32, + 32,32,32,32,108,111,97,100,105,110,103,46,105,1,0,0, + 0,105,0,0,0,0,117,1,0,0,0,46,40,16,0,0, + 0,117,8,0,0,0,95,95,110,97,109,101,95,95,117,8, + 0,0,0,103,101,116,95,99,111,100,101,117,12,0,0,0, + 103,101,116,95,102,105,108,101,110,97,109,101,117,8,0,0, + 0,95,95,102,105,108,101,95,95,117,4,0,0,0,95,105, + 109,112,117,17,0,0,0,99,97,99,104,101,95,102,114,111, + 109,95,115,111,117,114,99,101,117,10,0,0,0,95,95,99, + 97,99,104,101,100,95,95,117,11,0,0,0,95,95,112,97, + 99,107,97,103,101,95,95,117,10,0,0,0,105,115,95,112, + 97,99,107,97,103,101,117,6,0,0,0,114,115,112,108,105, + 116,117,8,0,0,0,112,97,116,104,95,115,101,112,117,8, + 0,0,0,95,95,112,97,116,104,95,95,117,10,0,0,0, + 114,112,97,114,116,105,116,105,111,110,117,10,0,0,0,95, + 95,108,111,97,100,101,114,95,95,117,4,0,0,0,101,120, + 101,99,117,8,0,0,0,95,95,100,105,99,116,95,95,40, + 5,0,0,0,117,4,0,0,0,115,101,108,102,117,6,0, + 0,0,109,111,100,117,108,101,117,10,0,0,0,115,111,117, + 114,99,101,108,101,115,115,117,4,0,0,0,110,97,109,101, + 117,11,0,0,0,99,111,100,101,95,111,98,106,101,99,116, + 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,117,12,0,0, + 0,95,108,111,97,100,95,109,111,100,117,108,101,183,1,0, + 0,115,26,0,0,0,0,4,9,1,15,1,18,1,6,1, + 24,2,12,1,9,1,15,1,34,2,25,1,9,1,16,1, + 117,26,0,0,0,95,76,111,97,100,101,114,66,97,115,105, + 99,115,46,95,108,111,97,100,95,109,111,100,117,108,101,78, + 70,40,9,0,0,0,117,8,0,0,0,95,95,110,97,109, + 101,95,95,117,10,0,0,0,95,95,109,111,100,117,108,101, + 95,95,117,12,0,0,0,95,95,113,117,97,108,110,97,109, + 101,95,95,117,7,0,0,0,95,95,100,111,99,95,95,117, + 10,0,0,0,105,115,95,112,97,99,107,97,103,101,117,20, + 0,0,0,95,98,121,116,101,115,95,102,114,111,109,95,98, + 121,116,101,99,111,100,101,117,17,0,0,0,109,111,100,117, + 108,101,95,102,111,114,95,108,111,97,100,101,114,117,5,0, + 0,0,70,97,108,115,101,117,12,0,0,0,95,108,111,97, + 100,95,109,111,100,117,108,101,40,1,0,0,0,117,10,0, + 0,0,95,95,108,111,99,97,108,115,95,95,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,13,0,0,0,95,76,111, + 97,100,101,114,66,97,115,105,99,115,127,1,0,0,115,10, + 0,0,0,16,3,6,2,12,6,12,45,6,1,117,13,0, + 0,0,95,76,111,97,100,101,114,66,97,115,105,99,115,99, + 1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, + 66,0,0,0,115,92,0,0,0,124,0,0,69,101,0,0, + 90,1,0,100,0,0,90,2,0,100,1,0,100,2,0,132, + 0,0,90,3,0,100,3,0,100,4,0,132,0,0,90,4, + 0,100,5,0,100,6,0,132,0,0,90,5,0,100,7,0, + 100,8,0,132,0,0,90,6,0,100,9,0,100,10,0,132, + 0,0,90,7,0,100,11,0,100,12,0,132,0,0,90,8, + 0,100,13,0,83,40,14,0,0,0,117,12,0,0,0,83, + 111,117,114,99,101,76,111,97,100,101,114,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,10,0,0,0,116,0,0,130,1,0,100,1,0,83,40, + 2,0,0,0,117,121,0,0,0,79,112,116,105,111,110,97, + 108,32,109,101,116,104,111,100,32,116,104,97,116,32,114,101, + 116,117,114,110,115,32,116,104,101,32,109,111,100,105,102,105, + 99,97,116,105,111,110,32,116,105,109,101,32,40,97,110,32, + 105,110,116,41,32,102,111,114,32,116,104,101,10,32,32,32, + 32,32,32,32,32,115,112,101,99,105,102,105,101,100,32,112, + 97,116,104,44,32,119,104,101,114,101,32,112,97,116,104,32, + 105,115,32,97,32,115,116,114,46,10,32,32,32,32,32,32, + 32,32,78,40,1,0,0,0,117,19,0,0,0,78,111,116, + 73,109,112,108,101,109,101,110,116,101,100,69,114,114,111,114, + 40,2,0,0,0,117,4,0,0,0,115,101,108,102,117,4, + 0,0,0,112,97,116,104,40,0,0,0,0,40,0,0,0, + 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, + 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, + 97,112,62,117,10,0,0,0,112,97,116,104,95,109,116,105, + 109,101,206,1,0,0,115,2,0,0,0,0,4,117,23,0, + 0,0,83,111,117,114,99,101,76,111,97,100,101,114,46,112, + 97,116,104,95,109,116,105,109,101,99,2,0,0,0,0,0, + 0,0,2,0,0,0,3,0,0,0,67,0,0,0,115,20, + 0,0,0,105,1,0,124,0,0,106,0,0,124,1,0,131, + 1,0,100,1,0,54,83,40,2,0,0,0,117,114,1,0, + 0,79,112,116,105,111,110,97,108,32,109,101,116,104,111,100, + 32,114,101,116,117,114,110,105,110,103,32,97,32,109,101,116, + 97,100,97,116,97,32,100,105,99,116,32,102,111,114,32,116, + 104,101,32,115,112,101,99,105,102,105,101,100,32,112,97,116, + 104,10,32,32,32,32,32,32,32,32,116,111,32,98,121,32, + 116,104,101,32,112,97,116,104,32,40,115,116,114,41,46,10, + 32,32,32,32,32,32,32,32,80,111,115,115,105,98,108,101, + 32,107,101,121,115,58,10,32,32,32,32,32,32,32,32,45, + 32,39,109,116,105,109,101,39,32,40,109,97,110,100,97,116, + 111,114,121,41,32,105,115,32,116,104,101,32,110,117,109,101, + 114,105,99,32,116,105,109,101,115,116,97,109,112,32,111,102, + 32,108,97,115,116,32,115,111,117,114,99,101,10,32,32,32, + 32,32,32,32,32,32,32,99,111,100,101,32,109,111,100,105, + 102,105,99,97,116,105,111,110,59,10,32,32,32,32,32,32, + 32,32,45,32,39,115,105,122,101,39,32,40,111,112,116,105, + 111,110,97,108,41,32,105,115,32,116,104,101,32,115,105,122, + 101,32,105,110,32,98,121,116,101,115,32,111,102,32,116,104, + 101,32,115,111,117,114,99,101,32,99,111,100,101,46,10,10, + 32,32,32,32,32,32,32,32,73,109,112,108,101,109,101,110, + 116,105,110,103,32,116,104,105,115,32,109,101,116,104,111,100, + 32,97,108,108,111,119,115,32,116,104,101,32,108,111,97,100, + 101,114,32,116,111,32,114,101,97,100,32,98,121,116,101,99, + 111,100,101,32,102,105,108,101,115,46,10,32,32,32,32,32, + 32,32,32,117,5,0,0,0,109,116,105,109,101,40,1,0, + 0,0,117,10,0,0,0,112,97,116,104,95,109,116,105,109, + 101,40,2,0,0,0,117,4,0,0,0,115,101,108,102,117, + 4,0,0,0,112,97,116,104,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,10,0,0,0,112,97,116,104,95,115,116, + 97,116,115,212,1,0,0,115,2,0,0,0,0,10,117,23, + 0,0,0,83,111,117,114,99,101,76,111,97,100,101,114,46, + 112,97,116,104,95,115,116,97,116,115,99,3,0,0,0,0, + 0,0,0,3,0,0,0,1,0,0,0,67,0,0,0,115, + 10,0,0,0,116,0,0,130,1,0,100,1,0,83,40,2, + 0,0,0,117,151,0,0,0,79,112,116,105,111,110,97,108, + 32,109,101,116,104,111,100,32,119,104,105,99,104,32,119,114, + 105,116,101,115,32,100,97,116,97,32,40,98,121,116,101,115, + 41,32,116,111,32,97,32,102,105,108,101,32,112,97,116,104, + 32,40,97,32,115,116,114,41,46,10,10,32,32,32,32,32, + 32,32,32,73,109,112,108,101,109,101,110,116,105,110,103,32, + 116,104,105,115,32,109,101,116,104,111,100,32,97,108,108,111, + 119,115,32,102,111,114,32,116,104,101,32,119,114,105,116,105, + 110,103,32,111,102,32,98,121,116,101,99,111,100,101,32,102, + 105,108,101,115,46,10,10,32,32,32,32,32,32,32,32,78, + 40,1,0,0,0,117,19,0,0,0,78,111,116,73,109,112, + 108,101,109,101,110,116,101,100,69,114,114,111,114,40,3,0, + 0,0,117,4,0,0,0,115,101,108,102,117,4,0,0,0, + 112,97,116,104,117,4,0,0,0,100,97,116,97,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,8,0,0,0,115,101, + 116,95,100,97,116,97,224,1,0,0,115,2,0,0,0,0, + 6,117,21,0,0,0,83,111,117,114,99,101,76,111,97,100, + 101,114,46,115,101,116,95,100,97,116,97,99,2,0,0,0, + 0,0,0,0,7,0,0,0,12,0,0,0,67,0,0,0, + 115,156,0,0,0,100,1,0,100,2,0,108,0,0,125,2, + 0,124,0,0,106,1,0,124,1,0,131,1,0,125,3,0, + 121,19,0,124,0,0,106,2,0,124,3,0,131,1,0,125, + 4,0,87,110,36,0,4,116,3,0,107,10,0,114,84,0, + 1,1,1,116,4,0,100,3,0,100,4,0,124,1,0,131, + 1,1,130,1,0,89,110,1,0,88,124,2,0,106,5,0, + 116,6,0,106,7,0,124,4,0,131,1,0,106,8,0,131, + 1,0,125,5,0,116,6,0,106,9,0,100,2,0,100,5, + 0,131,2,0,125,6,0,124,6,0,106,12,0,124,4,0, + 106,12,0,124,5,0,100,1,0,25,131,1,0,131,1,0, + 83,40,6,0,0,0,117,52,0,0,0,67,111,110,99,114, + 101,116,101,32,105,109,112,108,101,109,101,110,116,97,116,105, + 111,110,32,111,102,32,73,110,115,112,101,99,116,76,111,97, + 100,101,114,46,103,101,116,95,115,111,117,114,99,101,46,105, + 0,0,0,0,78,117,39,0,0,0,115,111,117,114,99,101, + 32,110,111,116,32,97,118,97,105,108,97,98,108,101,32,116, + 104,114,111,117,103,104,32,103,101,116,95,100,97,116,97,40, + 41,117,4,0,0,0,110,97,109,101,84,40,13,0,0,0, + 117,8,0,0,0,116,111,107,101,110,105,122,101,117,12,0, + 0,0,103,101,116,95,102,105,108,101,110,97,109,101,117,8, + 0,0,0,103,101,116,95,100,97,116,97,117,7,0,0,0, + 73,79,69,114,114,111,114,117,11,0,0,0,73,109,112,111, + 114,116,69,114,114,111,114,117,15,0,0,0,100,101,116,101, + 99,116,95,101,110,99,111,100,105,110,103,117,3,0,0,0, + 95,105,111,117,7,0,0,0,66,121,116,101,115,73,79,117, + 8,0,0,0,114,101,97,100,108,105,110,101,117,25,0,0, + 0,73,110,99,114,101,109,101,110,116,97,108,78,101,119,108, + 105,110,101,68,101,99,111,100,101,114,117,4,0,0,0,78, + 111,110,101,117,4,0,0,0,84,114,117,101,117,6,0,0, + 0,100,101,99,111,100,101,40,7,0,0,0,117,4,0,0, + 0,115,101,108,102,117,8,0,0,0,102,117,108,108,110,97, + 109,101,117,8,0,0,0,116,111,107,101,110,105,122,101,117, + 4,0,0,0,112,97,116,104,117,12,0,0,0,115,111,117, + 114,99,101,95,98,121,116,101,115,117,8,0,0,0,101,110, + 99,111,100,105,110,103,117,15,0,0,0,110,101,119,108,105, + 110,101,95,100,101,99,111,100,101,114,40,0,0,0,0,40, 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,11,0,0,0,108,111,97,100,95, - 109,111,100,117,108,101,47,1,0,0,115,14,0,0,0,0, - 6,15,1,3,1,17,1,3,1,22,1,13,1,117,27,0, - 0,0,66,117,105,108,116,105,110,73,109,112,111,114,116,101, - 114,46,108,111,97,100,95,109,111,100,117,108,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,1,0,83,40,2,0,0,0, - 117,57,0,0,0,82,101,116,117,114,110,32,78,111,110,101, - 32,97,115,32,98,117,105,108,116,45,105,110,32,109,111,100, - 117,108,101,115,32,100,111,32,110,111,116,32,104,97,118,101, - 32,99,111,100,101,32,111,98,106,101,99,116,115,46,78,40, - 1,0,0,0,117,4,0,0,0,78,111,110,101,40,2,0, - 0,0,117,3,0,0,0,99,108,115,117,8,0,0,0,102, - 117,108,108,110,97,109,101,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,8,0,0,0,103,101,116,95,99,111,100,101, - 61,1,0,0,115,2,0,0,0,0,4,117,24,0,0,0, - 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,46, - 103,101,116,95,99,111,100,101,99,2,0,0,0,0,0,0, - 0,2,0,0,0,1,0,0,0,67,0,0,0,115,4,0, - 0,0,100,1,0,83,40,2,0,0,0,117,56,0,0,0, - 82,101,116,117,114,110,32,78,111,110,101,32,97,115,32,98, - 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,32, - 100,111,32,110,111,116,32,104,97,118,101,32,115,111,117,114, - 99,101,32,99,111,100,101,46,78,40,1,0,0,0,117,4, - 0,0,0,78,111,110,101,40,2,0,0,0,117,3,0,0, - 0,99,108,115,117,8,0,0,0,102,117,108,108,110,97,109, - 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,10,0, - 0,0,103,101,116,95,115,111,117,114,99,101,67,1,0,0, - 115,2,0,0,0,0,4,117,26,0,0,0,66,117,105,108, - 116,105,110,73,109,112,111,114,116,101,114,46,103,101,116,95, - 115,111,117,114,99,101,99,2,0,0,0,0,0,0,0,2, - 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, - 100,1,0,83,40,2,0,0,0,117,51,0,0,0,82,101, - 116,117,114,110,32,78,111,110,101,32,97,115,32,98,117,105, - 108,116,45,105,110,32,109,111,100,117,108,101,115,32,97,114, - 101,32,110,101,118,101,114,32,112,97,99,107,97,103,101,115, - 46,70,40,1,0,0,0,117,5,0,0,0,70,97,108,115, - 101,40,2,0,0,0,117,3,0,0,0,99,108,115,117,8, + 115,116,114,97,112,62,117,10,0,0,0,103,101,116,95,115, + 111,117,114,99,101,233,1,0,0,115,20,0,0,0,0,2, + 12,1,15,1,3,1,19,1,13,1,9,1,14,1,27,1, + 18,1,117,23,0,0,0,83,111,117,114,99,101,76,111,97, + 100,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, + 0,0,0,0,0,0,0,12,0,0,0,37,0,0,0,67, + 0,0,0,115,39,2,0,0,124,0,0,106,0,0,124,1, + 0,131,1,0,125,2,0,116,1,0,106,2,0,124,2,0, + 131,1,0,125,3,0,100,10,0,125,4,0,124,3,0,100, + 10,0,107,9,0,114,64,1,121,19,0,124,0,0,106,4, + 0,124,2,0,131,1,0,125,5,0,87,110,18,0,4,116, + 5,0,107,10,0,114,87,0,1,1,1,89,113,64,1,88, + 116,6,0,124,5,0,100,1,0,25,131,1,0,125,4,0, + 121,19,0,124,0,0,106,7,0,124,3,0,131,1,0,125, + 6,0,87,110,18,0,4,116,8,0,107,10,0,114,143,0, + 1,1,1,89,113,64,1,88,121,28,0,124,0,0,106,9, + 0,124,1,0,124,6,0,124,3,0,124,5,0,131,4,0, + 125,7,0,87,110,24,0,4,116,10,0,116,11,0,102,2, + 0,107,10,0,114,198,0,1,1,1,89,113,64,1,88,116, + 12,0,100,2,0,124,3,0,124,2,0,131,3,0,1,116, + 13,0,106,14,0,124,7,0,131,1,0,125,8,0,116,15, + 0,124,8,0,116,16,0,131,2,0,114,22,1,116,1,0, + 106,17,0,124,8,0,124,2,0,131,2,0,1,116,12,0, + 100,3,0,124,3,0,131,2,0,1,124,8,0,83,100,4, + 0,125,9,0,116,10,0,124,9,0,106,18,0,124,3,0, + 131,1,0,100,5,0,124,1,0,100,6,0,124,3,0,131, + 1,2,130,1,0,110,0,0,124,0,0,106,7,0,124,2, + 0,131,1,0,125,10,0,116,19,0,124,10,0,124,2,0, + 100,7,0,100,8,0,100,11,0,131,3,1,125,11,0,116, + 12,0,100,3,0,124,2,0,131,2,0,1,116,21,0,106, + 22,0,12,114,35,2,124,3,0,100,10,0,107,9,0,114, + 35,2,124,4,0,100,10,0,107,9,0,114,35,2,116,23, + 0,116,1,0,106,24,0,131,0,0,131,1,0,125,6,0, + 124,6,0,106,25,0,116,26,0,124,4,0,131,1,0,131, + 1,0,1,124,6,0,106,25,0,116,26,0,116,27,0,124, + 10,0,131,1,0,131,1,0,131,1,0,1,124,6,0,106, + 25,0,116,13,0,106,28,0,124,11,0,131,1,0,131,1, + 0,1,121,33,0,124,0,0,106,29,0,124,3,0,124,6, + 0,131,2,0,1,116,12,0,100,9,0,124,3,0,131,2, + 0,1,87,113,35,2,4,116,5,0,107,10,0,114,31,2, + 1,1,1,89,113,35,2,88,110,0,0,124,11,0,83,40, + 12,0,0,0,117,190,0,0,0,67,111,110,99,114,101,116, + 101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110, + 32,111,102,32,73,110,115,112,101,99,116,76,111,97,100,101, + 114,46,103,101,116,95,99,111,100,101,46,10,10,32,32,32, + 32,32,32,32,32,82,101,97,100,105,110,103,32,111,102,32, + 98,121,116,101,99,111,100,101,32,114,101,113,117,105,114,101, + 115,32,112,97,116,104,95,115,116,97,116,115,32,116,111,32, + 98,101,32,105,109,112,108,101,109,101,110,116,101,100,46,32, + 84,111,32,119,114,105,116,101,10,32,32,32,32,32,32,32, + 32,98,121,116,101,99,111,100,101,44,32,115,101,116,95,100, + 97,116,97,32,109,117,115,116,32,97,108,115,111,32,98,101, + 32,105,109,112,108,101,109,101,110,116,101,100,46,10,10,32, + 32,32,32,32,32,32,32,117,5,0,0,0,109,116,105,109, + 101,117,13,0,0,0,123,125,32,109,97,116,99,104,101,115, + 32,123,125,117,19,0,0,0,99,111,100,101,32,111,98,106, + 101,99,116,32,102,114,111,109,32,123,125,117,21,0,0,0, + 78,111,110,45,99,111,100,101,32,111,98,106,101,99,116,32, + 105,110,32,123,125,117,4,0,0,0,110,97,109,101,117,4, + 0,0,0,112,97,116,104,117,4,0,0,0,101,120,101,99, + 117,12,0,0,0,100,111,110,116,95,105,110,104,101,114,105, + 116,117,10,0,0,0,119,114,111,116,101,32,123,33,114,125, + 78,84,40,30,0,0,0,117,12,0,0,0,103,101,116,95, + 102,105,108,101,110,97,109,101,117,4,0,0,0,95,105,109, + 112,117,17,0,0,0,99,97,99,104,101,95,102,114,111,109, + 95,115,111,117,114,99,101,117,4,0,0,0,78,111,110,101, + 117,10,0,0,0,112,97,116,104,95,115,116,97,116,115,117, + 19,0,0,0,78,111,116,73,109,112,108,101,109,101,110,116, + 101,100,69,114,114,111,114,117,3,0,0,0,105,110,116,117, + 8,0,0,0,103,101,116,95,100,97,116,97,117,7,0,0, + 0,73,79,69,114,114,111,114,117,20,0,0,0,95,98,121, + 116,101,115,95,102,114,111,109,95,98,121,116,101,99,111,100, + 101,117,11,0,0,0,73,109,112,111,114,116,69,114,114,111, + 114,117,8,0,0,0,69,79,70,69,114,114,111,114,117,15, + 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, + 103,101,117,7,0,0,0,109,97,114,115,104,97,108,117,5, + 0,0,0,108,111,97,100,115,117,10,0,0,0,105,115,105, + 110,115,116,97,110,99,101,117,9,0,0,0,99,111,100,101, + 95,116,121,112,101,117,16,0,0,0,95,102,105,120,95,99, + 111,95,102,105,108,101,110,97,109,101,117,6,0,0,0,102, + 111,114,109,97,116,117,7,0,0,0,99,111,109,112,105,108, + 101,117,4,0,0,0,84,114,117,101,117,3,0,0,0,115, + 121,115,117,19,0,0,0,100,111,110,116,95,119,114,105,116, + 101,95,98,121,116,101,99,111,100,101,117,9,0,0,0,98, + 121,116,101,97,114,114,97,121,117,9,0,0,0,103,101,116, + 95,109,97,103,105,99,117,6,0,0,0,101,120,116,101,110, + 100,117,7,0,0,0,95,119,95,108,111,110,103,117,3,0, + 0,0,108,101,110,117,5,0,0,0,100,117,109,112,115,117, + 8,0,0,0,115,101,116,95,100,97,116,97,40,12,0,0, + 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,102, + 117,108,108,110,97,109,101,117,11,0,0,0,115,111,117,114, + 99,101,95,112,97,116,104,117,13,0,0,0,98,121,116,101, + 99,111,100,101,95,112,97,116,104,117,12,0,0,0,115,111, + 117,114,99,101,95,109,116,105,109,101,117,2,0,0,0,115, + 116,117,4,0,0,0,100,97,116,97,117,10,0,0,0,98, + 121,116,101,115,95,100,97,116,97,117,5,0,0,0,102,111, + 117,110,100,117,3,0,0,0,109,115,103,117,12,0,0,0, + 115,111,117,114,99,101,95,98,121,116,101,115,117,11,0,0, + 0,99,111,100,101,95,111,98,106,101,99,116,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,8,0,0,0,103,101,116, + 95,99,111,100,101,246,1,0,0,115,92,0,0,0,0,7, + 15,1,15,1,6,1,12,1,3,1,19,1,13,1,5,2, + 16,1,3,1,19,1,13,1,5,2,3,1,12,1,3,1, + 13,1,19,1,5,2,9,1,7,1,15,1,15,1,16,1, + 6,1,7,1,4,2,6,1,18,1,18,1,15,1,15,1, + 9,1,13,1,22,1,12,4,18,1,19,1,25,1,22,1, + 3,1,16,1,17,1,13,1,8,1,117,21,0,0,0,83, + 111,117,114,99,101,76,111,97,100,101,114,46,103,101,116,95, + 99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,2,0,0,0,67,0,0,0,115,13,0,0,0,124,0, + 0,106,0,0,124,1,0,131,1,0,83,40,1,0,0,0, + 117,0,1,0,0,67,111,110,99,114,101,116,101,32,105,109, + 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, + 76,111,97,100,101,114,46,108,111,97,100,95,109,111,100,117, + 108,101,46,10,10,32,32,32,32,32,32,32,32,82,101,113, + 117,105,114,101,115,32,69,120,101,99,117,116,105,111,110,76, + 111,97,100,101,114,46,103,101,116,95,102,105,108,101,110,97, + 109,101,32,97,110,100,32,82,101,115,111,117,114,99,101,76, + 111,97,100,101,114,46,103,101,116,95,100,97,116,97,32,116, + 111,32,98,101,10,32,32,32,32,32,32,32,32,105,109,112, + 108,101,109,101,110,116,101,100,32,116,111,32,108,111,97,100, + 32,115,111,117,114,99,101,32,99,111,100,101,46,32,85,115, + 101,32,111,102,32,98,121,116,101,99,111,100,101,32,105,115, + 32,100,105,99,116,97,116,101,100,32,98,121,32,119,104,101, + 116,104,101,114,10,32,32,32,32,32,32,32,32,103,101,116, + 95,99,111,100,101,32,117,115,101,115,47,119,114,105,116,101, + 115,32,98,121,116,101,99,111,100,101,46,10,10,32,32,32, + 32,32,32,32,32,40,1,0,0,0,117,12,0,0,0,95, + 108,111,97,100,95,109,111,100,117,108,101,40,2,0,0,0, + 117,4,0,0,0,115,101,108,102,117,8,0,0,0,102,117, + 108,108,110,97,109,101,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,11,0,0,0,108,111,97,100,95,109,111,100,117, + 108,101,51,2,0,0,115,2,0,0,0,0,8,117,24,0, + 0,0,83,111,117,114,99,101,76,111,97,100,101,114,46,108, + 111,97,100,95,109,111,100,117,108,101,78,40,9,0,0,0, + 117,8,0,0,0,95,95,110,97,109,101,95,95,117,10,0, + 0,0,95,95,109,111,100,117,108,101,95,95,117,12,0,0, + 0,95,95,113,117,97,108,110,97,109,101,95,95,117,10,0, + 0,0,112,97,116,104,95,109,116,105,109,101,117,10,0,0, + 0,112,97,116,104,95,115,116,97,116,115,117,8,0,0,0, + 115,101,116,95,100,97,116,97,117,10,0,0,0,103,101,116, + 95,115,111,117,114,99,101,117,8,0,0,0,103,101,116,95, + 99,111,100,101,117,11,0,0,0,108,111,97,100,95,109,111, + 100,117,108,101,40,1,0,0,0,117,10,0,0,0,95,95, + 108,111,99,97,108,115,95,95,40,0,0,0,0,40,0,0, + 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,12,0,0,0,83,111,117,114,99,101,76, + 111,97,100,101,114,204,1,0,0,115,12,0,0,0,16,2, + 12,6,12,12,12,9,12,13,12,61,117,12,0,0,0,83, + 111,117,114,99,101,76,111,97,100,101,114,99,1,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,66,0,0,0, + 115,68,0,0,0,124,0,0,69,101,0,0,90,1,0,100, + 0,0,90,2,0,100,1,0,90,3,0,100,2,0,100,3, + 0,132,0,0,90,4,0,101,5,0,100,4,0,100,5,0, + 132,0,0,131,1,0,90,6,0,100,6,0,100,7,0,132, + 0,0,90,7,0,100,8,0,83,40,9,0,0,0,117,11, + 0,0,0,95,70,105,108,101,76,111,97,100,101,114,117,103, + 0,0,0,66,97,115,101,32,102,105,108,101,32,108,111,97, + 100,101,114,32,99,108,97,115,115,32,119,104,105,99,104,32, + 105,109,112,108,101,109,101,110,116,115,32,116,104,101,32,108, + 111,97,100,101,114,32,112,114,111,116,111,99,111,108,32,109, + 101,116,104,111,100,115,32,116,104,97,116,10,32,32,32,32, + 114,101,113,117,105,114,101,32,102,105,108,101,32,115,121,115, + 116,101,109,32,117,115,97,103,101,46,99,3,0,0,0,0, + 0,0,0,3,0,0,0,2,0,0,0,67,0,0,0,115, + 22,0,0,0,124,1,0,124,0,0,95,0,0,124,2,0, + 124,0,0,95,1,0,100,1,0,83,40,2,0,0,0,117, + 75,0,0,0,67,97,99,104,101,32,116,104,101,32,109,111, + 100,117,108,101,32,110,97,109,101,32,97,110,100,32,116,104, + 101,32,112,97,116,104,32,116,111,32,116,104,101,32,102,105, + 108,101,32,102,111,117,110,100,32,98,121,32,116,104,101,10, + 32,32,32,32,32,32,32,32,102,105,110,100,101,114,46,78, + 40,2,0,0,0,117,5,0,0,0,95,110,97,109,101,117, + 5,0,0,0,95,112,97,116,104,40,3,0,0,0,117,4, + 0,0,0,115,101,108,102,117,8,0,0,0,102,117,108,108, + 110,97,109,101,117,4,0,0,0,112,97,116,104,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,8,0,0,0,95,95, + 105,110,105,116,95,95,67,2,0,0,115,4,0,0,0,0, + 3,9,1,117,20,0,0,0,95,70,105,108,101,76,111,97, + 100,101,114,46,95,95,105,110,105,116,95,95,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,7,0,0,0,124,0,0,106,0,0,83,40,1,0, + 0,0,117,58,0,0,0,82,101,116,117,114,110,32,116,104, + 101,32,112,97,116,104,32,116,111,32,116,104,101,32,115,111, + 117,114,99,101,32,102,105,108,101,32,97,115,32,102,111,117, + 110,100,32,98,121,32,116,104,101,32,102,105,110,100,101,114, + 46,40,1,0,0,0,117,5,0,0,0,95,112,97,116,104, + 40,2,0,0,0,117,4,0,0,0,115,101,108,102,117,8, 0,0,0,102,117,108,108,110,97,109,101,40,0,0,0,0, 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, - 116,115,116,114,97,112,62,117,10,0,0,0,105,115,95,112, - 97,99,107,97,103,101,73,1,0,0,115,2,0,0,0,0, - 4,117,26,0,0,0,66,117,105,108,116,105,110,73,109,112, - 111,114,116,101,114,46,105,115,95,112,97,99,107,97,103,101, - 78,40,14,0,0,0,117,8,0,0,0,95,95,110,97,109, - 101,95,95,117,10,0,0,0,95,95,109,111,100,117,108,101, - 95,95,117,12,0,0,0,95,95,113,117,97,108,110,97,109, - 101,95,95,117,7,0,0,0,95,95,100,111,99,95,95,117, - 11,0,0,0,99,108,97,115,115,109,101,116,104,111,100,117, - 4,0,0,0,78,111,110,101,117,11,0,0,0,102,105,110, - 100,95,109,111,100,117,108,101,117,11,0,0,0,115,101,116, - 95,112,97,99,107,97,103,101,117,10,0,0,0,115,101,116, - 95,108,111,97,100,101,114,117,17,0,0,0,95,114,101,113, - 117,105,114,101,115,95,98,117,105,108,116,105,110,117,11,0, - 0,0,108,111,97,100,95,109,111,100,117,108,101,117,8,0, - 0,0,103,101,116,95,99,111,100,101,117,10,0,0,0,103, - 101,116,95,115,111,117,114,99,101,117,10,0,0,0,105,115, - 95,112,97,99,107,97,103,101,40,1,0,0,0,117,10,0, - 0,0,95,95,108,111,99,97,108,115,95,95,40,0,0,0, + 116,115,116,114,97,112,62,117,12,0,0,0,103,101,116,95, + 102,105,108,101,110,97,109,101,73,2,0,0,115,2,0,0, + 0,0,3,117,24,0,0,0,95,70,105,108,101,76,111,97, + 100,101,114,46,103,101,116,95,102,105,108,101,110,97,109,101, + 99,2,0,0,0,0,0,0,0,3,0,0,0,8,0,0, + 0,67,0,0,0,115,41,0,0,0,116,0,0,106,1,0, + 124,1,0,100,1,0,131,2,0,143,17,0,125,2,0,124, + 2,0,106,2,0,131,0,0,83,87,100,2,0,81,88,100, + 2,0,83,40,3,0,0,0,117,39,0,0,0,82,101,116, + 117,114,110,32,116,104,101,32,100,97,116,97,32,102,114,111, + 109,32,112,97,116,104,32,97,115,32,114,97,119,32,98,121, + 116,101,115,46,117,1,0,0,0,114,78,40,3,0,0,0, + 117,3,0,0,0,95,105,111,117,6,0,0,0,70,105,108, + 101,73,79,117,4,0,0,0,114,101,97,100,40,3,0,0, + 0,117,4,0,0,0,115,101,108,102,117,4,0,0,0,112, + 97,116,104,117,4,0,0,0,102,105,108,101,40,0,0,0, 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, - 111,116,115,116,114,97,112,62,117,15,0,0,0,66,117,105, - 108,116,105,110,73,109,112,111,114,116,101,114,27,1,0,0, - 115,26,0,0,0,16,7,6,2,3,1,18,10,3,1,3, - 1,3,1,27,11,3,1,21,5,3,1,21,5,3,1,117, - 15,0,0,0,66,117,105,108,116,105,110,73,109,112,111,114, - 116,101,114,99,1,0,0,0,0,0,0,0,1,0,0,0, - 6,0,0,0,66,0,0,0,115,155,0,0,0,124,0,0, - 69,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, - 90,3,0,101,4,0,100,12,0,100,2,0,100,3,0,132, - 1,0,131,1,0,90,6,0,101,4,0,101,7,0,101,8, - 0,101,9,0,100,4,0,100,5,0,132,0,0,131,1,0, - 131,1,0,131,1,0,131,1,0,90,10,0,101,4,0,101, - 9,0,100,6,0,100,7,0,132,0,0,131,1,0,131,1, - 0,90,11,0,101,4,0,101,9,0,100,8,0,100,9,0, - 132,0,0,131,1,0,131,1,0,90,12,0,101,4,0,101, - 9,0,100,10,0,100,11,0,132,0,0,131,1,0,131,1, - 0,90,13,0,100,12,0,83,40,13,0,0,0,117,14,0, - 0,0,70,114,111,122,101,110,73,109,112,111,114,116,101,114, - 117,142,0,0,0,77,101,116,97,32,112,97,116,104,32,105, - 109,112,111,114,116,32,102,111,114,32,102,114,111,122,101,110, - 32,109,111,100,117,108,101,115,46,10,10,32,32,32,32,65, - 108,108,32,109,101,116,104,111,100,115,32,97,114,101,32,101, - 105,116,104,101,114,32,99,108,97,115,115,32,111,114,32,115, - 116,97,116,105,99,32,109,101,116,104,111,100,115,32,116,111, - 32,97,118,111,105,100,32,116,104,101,32,110,101,101,100,32, - 116,111,10,32,32,32,32,105,110,115,116,97,110,116,105,97, - 116,101,32,116,104,101,32,99,108,97,115,115,46,10,10,32, - 32,32,32,99,3,0,0,0,0,0,0,0,3,0,0,0, - 2,0,0,0,67,0,0,0,115,23,0,0,0,116,0,0, - 106,1,0,124,1,0,131,1,0,114,19,0,124,0,0,83, - 100,1,0,83,40,2,0,0,0,117,21,0,0,0,70,105, - 110,100,32,97,32,102,114,111,122,101,110,32,109,111,100,117, - 108,101,46,78,40,3,0,0,0,117,4,0,0,0,95,105, - 109,112,117,9,0,0,0,105,115,95,102,114,111,122,101,110, - 117,4,0,0,0,78,111,110,101,40,3,0,0,0,117,3, - 0,0,0,99,108,115,117,8,0,0,0,102,117,108,108,110, - 97,109,101,117,4,0,0,0,112,97,116,104,40,0,0,0, + 111,116,115,116,114,97,112,62,117,8,0,0,0,103,101,116, + 95,100,97,116,97,78,2,0,0,115,4,0,0,0,0,2, + 21,1,117,20,0,0,0,95,70,105,108,101,76,111,97,100, + 101,114,46,103,101,116,95,100,97,116,97,78,40,8,0,0, + 0,117,8,0,0,0,95,95,110,97,109,101,95,95,117,10, + 0,0,0,95,95,109,111,100,117,108,101,95,95,117,12,0, + 0,0,95,95,113,117,97,108,110,97,109,101,95,95,117,7, + 0,0,0,95,95,100,111,99,95,95,117,8,0,0,0,95, + 95,105,110,105,116,95,95,117,11,0,0,0,95,99,104,101, + 99,107,95,110,97,109,101,117,12,0,0,0,103,101,116,95, + 102,105,108,101,110,97,109,101,117,8,0,0,0,103,101,116, + 95,100,97,116,97,40,1,0,0,0,117,10,0,0,0,95, + 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,11,0,0,0,95,70,105,108,101,76, + 111,97,100,101,114,62,2,0,0,115,8,0,0,0,16,3, + 6,2,12,6,18,5,117,11,0,0,0,95,70,105,108,101, + 76,111,97,100,101,114,99,1,0,0,0,0,0,0,0,1, + 0,0,0,2,0,0,0,66,0,0,0,115,50,0,0,0, + 124,0,0,69,101,0,0,90,1,0,100,0,0,90,2,0, + 100,1,0,90,3,0,100,2,0,100,3,0,132,0,0,90, + 4,0,100,4,0,100,5,0,132,0,0,90,5,0,100,6, + 0,83,40,7,0,0,0,117,17,0,0,0,95,83,111,117, + 114,99,101,70,105,108,101,76,111,97,100,101,114,117,62,0, + 0,0,67,111,110,99,114,101,116,101,32,105,109,112,108,101, + 109,101,110,116,97,116,105,111,110,32,111,102,32,83,111,117, + 114,99,101,76,111,97,100,101,114,32,117,115,105,110,103,32, + 116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,46, + 99,2,0,0,0,0,0,0,0,3,0,0,0,3,0,0, + 0,67,0,0,0,115,39,0,0,0,116,0,0,106,1,0, + 124,1,0,131,1,0,125,2,0,105,2,0,124,2,0,106, + 2,0,100,1,0,54,124,2,0,106,3,0,100,2,0,54, + 83,40,3,0,0,0,117,32,0,0,0,82,101,116,117,114, + 110,32,116,104,101,32,109,101,116,97,100,97,116,32,102,111, + 114,32,116,104,101,32,112,97,116,104,46,117,5,0,0,0, + 109,116,105,109,101,117,4,0,0,0,115,105,122,101,40,4, + 0,0,0,117,3,0,0,0,95,111,115,117,4,0,0,0, + 115,116,97,116,117,8,0,0,0,115,116,95,109,116,105,109, + 101,117,7,0,0,0,115,116,95,115,105,122,101,40,3,0, + 0,0,117,4,0,0,0,115,101,108,102,117,4,0,0,0, + 112,97,116,104,117,2,0,0,0,115,116,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,10,0,0,0,112,97,116,104, + 95,115,116,97,116,115,88,2,0,0,115,4,0,0,0,0, + 2,15,1,117,28,0,0,0,95,83,111,117,114,99,101,70, + 105,108,101,76,111,97,100,101,114,46,112,97,116,104,95,115, + 116,97,116,115,99,3,0,0,0,0,0,0,0,8,0,0, + 0,13,0,0,0,67,0,0,0,115,254,0,0,0,124,1, + 0,106,0,0,116,1,0,131,1,0,92,3,0,125,3,0, + 125,4,0,125,5,0,103,0,0,125,6,0,120,60,0,124, + 3,0,114,92,0,116,2,0,124,3,0,131,1,0,12,114, + 92,0,124,3,0,106,0,0,116,1,0,131,1,0,92,3, + 0,125,3,0,125,4,0,125,7,0,124,6,0,106,3,0, + 124,7,0,131,1,0,1,113,33,0,87,120,97,0,116,4, + 0,124,6,0,131,1,0,68,93,83,0,125,7,0,116,5, + 0,124,3,0,124,7,0,131,2,0,125,3,0,121,17,0, + 116,6,0,106,7,0,124,3,0,131,1,0,1,87,113,106, + 0,4,116,8,0,107,10,0,114,167,0,1,1,1,119,106, + 0,89,113,106,0,4,116,9,0,107,10,0,114,188,0,1, + 1,1,100,1,0,83,89,113,106,0,88,113,106,0,87,121, + 30,0,116,10,0,124,1,0,124,2,0,131,2,0,1,116, + 11,0,100,2,0,124,1,0,131,2,0,1,87,110,24,0, + 4,116,9,0,116,8,0,102,2,0,107,10,0,114,249,0, + 1,1,1,89,110,1,0,88,100,1,0,83,40,3,0,0, + 0,117,27,0,0,0,87,114,105,116,101,32,98,121,116,101, + 115,32,100,97,116,97,32,116,111,32,97,32,102,105,108,101, + 46,78,117,12,0,0,0,99,114,101,97,116,101,100,32,123, + 33,114,125,40,12,0,0,0,117,10,0,0,0,114,112,97, + 114,116,105,116,105,111,110,117,8,0,0,0,112,97,116,104, + 95,115,101,112,117,11,0,0,0,95,112,97,116,104,95,105, + 115,100,105,114,117,6,0,0,0,97,112,112,101,110,100,117, + 8,0,0,0,114,101,118,101,114,115,101,100,117,10,0,0, + 0,95,112,97,116,104,95,106,111,105,110,117,3,0,0,0, + 95,111,115,117,5,0,0,0,109,107,100,105,114,117,15,0, + 0,0,70,105,108,101,69,120,105,115,116,115,69,114,114,111, + 114,117,15,0,0,0,80,101,114,109,105,115,115,105,111,110, + 69,114,114,111,114,117,13,0,0,0,95,119,114,105,116,101, + 95,97,116,111,109,105,99,117,15,0,0,0,118,101,114,98, + 111,115,101,95,109,101,115,115,97,103,101,40,8,0,0,0, + 117,4,0,0,0,115,101,108,102,117,4,0,0,0,112,97, + 116,104,117,4,0,0,0,100,97,116,97,117,6,0,0,0, + 112,97,114,101,110,116,117,1,0,0,0,95,117,8,0,0, + 0,102,105,108,101,110,97,109,101,117,10,0,0,0,112,97, + 116,104,95,112,97,114,116,115,117,4,0,0,0,112,97,114, + 116,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, + 0,0,115,101,116,95,100,97,116,97,93,2,0,0,115,36, + 0,0,0,0,2,24,1,6,2,22,1,24,1,17,2,19, + 1,15,1,3,1,17,1,13,2,7,1,13,3,13,1,3, + 1,13,1,17,1,19,3,117,26,0,0,0,95,83,111,117, + 114,99,101,70,105,108,101,76,111,97,100,101,114,46,115,101, + 116,95,100,97,116,97,78,40,6,0,0,0,117,8,0,0, + 0,95,95,110,97,109,101,95,95,117,10,0,0,0,95,95, + 109,111,100,117,108,101,95,95,117,12,0,0,0,95,95,113, + 117,97,108,110,97,109,101,95,95,117,7,0,0,0,95,95, + 100,111,99,95,95,117,10,0,0,0,112,97,116,104,95,115, + 116,97,116,115,117,8,0,0,0,115,101,116,95,100,97,116, + 97,40,1,0,0,0,117,10,0,0,0,95,95,108,111,99, + 97,108,115,95,95,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,17,0,0,0,95,83,111,117,114,99,101,70,105,108, + 101,76,111,97,100,101,114,84,2,0,0,115,6,0,0,0, + 16,2,6,2,12,5,117,17,0,0,0,95,83,111,117,114, + 99,101,70,105,108,101,76,111,97,100,101,114,99,1,0,0, + 0,0,0,0,0,1,0,0,0,2,0,0,0,66,0,0, + 0,115,62,0,0,0,124,0,0,69,101,0,0,90,1,0, + 100,0,0,90,2,0,100,1,0,90,3,0,100,2,0,100, + 3,0,132,0,0,90,4,0,100,4,0,100,5,0,132,0, + 0,90,5,0,100,6,0,100,7,0,132,0,0,90,6,0, + 100,8,0,83,40,9,0,0,0,117,21,0,0,0,95,83, + 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, + 100,101,114,117,45,0,0,0,76,111,97,100,101,114,32,119, + 104,105,99,104,32,104,97,110,100,108,101,115,32,115,111,117, + 114,99,101,108,101,115,115,32,102,105,108,101,32,105,109,112, + 111,114,116,115,46,99,2,0,0,0,0,0,0,0,2,0, + 0,0,4,0,0,0,67,0,0,0,115,19,0,0,0,124, + 0,0,106,0,0,124,1,0,100,1,0,100,2,0,131,1, + 1,83,40,3,0,0,0,78,117,10,0,0,0,115,111,117, + 114,99,101,108,101,115,115,84,40,2,0,0,0,117,12,0, + 0,0,95,108,111,97,100,95,109,111,100,117,108,101,117,4, + 0,0,0,84,114,117,101,40,2,0,0,0,117,4,0,0, + 0,115,101,108,102,117,8,0,0,0,102,117,108,108,110,97, + 109,101,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,11, + 0,0,0,108,111,97,100,95,109,111,100,117,108,101,126,2, + 0,0,115,2,0,0,0,0,1,117,33,0,0,0,95,83, + 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, + 100,101,114,46,108,111,97,100,95,109,111,100,117,108,101,99, + 2,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0, + 67,0,0,0,115,138,0,0,0,124,0,0,106,0,0,124, + 1,0,131,1,0,125,2,0,124,0,0,106,1,0,124,2, + 0,131,1,0,125,3,0,124,0,0,106,2,0,124,1,0, + 124,3,0,124,2,0,100,0,0,131,4,0,125,4,0,116, + 4,0,106,5,0,124,4,0,131,1,0,125,5,0,116,6, + 0,124,5,0,116,7,0,131,2,0,114,101,0,116,8,0, + 100,1,0,124,2,0,131,2,0,1,124,5,0,83,116,9, + 0,100,2,0,106,10,0,124,2,0,131,1,0,100,3,0, + 124,1,0,100,4,0,124,2,0,131,1,2,130,1,0,100, + 0,0,83,40,5,0,0,0,78,117,21,0,0,0,99,111, + 100,101,32,111,98,106,101,99,116,32,102,114,111,109,32,123, + 33,114,125,117,21,0,0,0,78,111,110,45,99,111,100,101, + 32,111,98,106,101,99,116,32,105,110,32,123,125,117,4,0, + 0,0,110,97,109,101,117,4,0,0,0,112,97,116,104,40, + 11,0,0,0,117,12,0,0,0,103,101,116,95,102,105,108, + 101,110,97,109,101,117,8,0,0,0,103,101,116,95,100,97, + 116,97,117,20,0,0,0,95,98,121,116,101,115,95,102,114, + 111,109,95,98,121,116,101,99,111,100,101,117,4,0,0,0, + 78,111,110,101,117,7,0,0,0,109,97,114,115,104,97,108, + 117,5,0,0,0,108,111,97,100,115,117,10,0,0,0,105, + 115,105,110,115,116,97,110,99,101,117,9,0,0,0,99,111, + 100,101,95,116,121,112,101,117,15,0,0,0,118,101,114,98, + 111,115,101,95,109,101,115,115,97,103,101,117,11,0,0,0, + 73,109,112,111,114,116,69,114,114,111,114,117,6,0,0,0, + 102,111,114,109,97,116,40,6,0,0,0,117,4,0,0,0, + 115,101,108,102,117,8,0,0,0,102,117,108,108,110,97,109, + 101,117,4,0,0,0,112,97,116,104,117,4,0,0,0,100, + 97,116,97,117,10,0,0,0,98,121,116,101,115,95,100,97, + 116,97,117,5,0,0,0,102,111,117,110,100,40,0,0,0, 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, - 111,116,115,116,114,97,112,62,117,11,0,0,0,102,105,110, - 100,95,109,111,100,117,108,101,89,1,0,0,115,2,0,0, - 0,0,3,117,26,0,0,0,70,114,111,122,101,110,73,109, - 112,111,114,116,101,114,46,102,105,110,100,95,109,111,100,117, - 108,101,99,2,0,0,0,0,0,0,0,3,0,0,0,9, - 0,0,0,67,0,0,0,115,85,0,0,0,124,1,0,116, - 0,0,106,1,0,107,6,0,125,2,0,121,17,0,116,2, - 0,106,3,0,124,1,0,131,1,0,83,87,110,46,0,1, - 1,1,124,2,0,12,114,73,0,124,1,0,116,0,0,106, - 1,0,107,6,0,114,73,0,116,0,0,106,1,0,124,1, - 0,61,110,0,0,130,0,0,89,110,1,0,88,100,1,0, - 83,40,2,0,0,0,117,21,0,0,0,76,111,97,100,32, - 97,32,102,114,111,122,101,110,32,109,111,100,117,108,101,46, - 78,40,4,0,0,0,117,3,0,0,0,115,121,115,117,7, - 0,0,0,109,111,100,117,108,101,115,117,4,0,0,0,95, - 105,109,112,117,11,0,0,0,105,110,105,116,95,102,114,111, - 122,101,110,40,3,0,0,0,117,3,0,0,0,99,108,115, - 117,8,0,0,0,102,117,108,108,110,97,109,101,117,9,0, - 0,0,105,115,95,114,101,108,111,97,100,40,0,0,0,0, - 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, - 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, - 116,115,116,114,97,112,62,117,11,0,0,0,108,111,97,100, - 95,109,111,100,117,108,101,94,1,0,0,115,14,0,0,0, - 0,6,15,1,3,1,17,1,3,1,22,1,13,1,117,26, - 0,0,0,70,114,111,122,101,110,73,109,112,111,114,116,101, - 114,46,108,111,97,100,95,109,111,100,117,108,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,2,0,0,0,67,0, - 0,0,115,13,0,0,0,116,0,0,106,1,0,124,1,0, - 131,1,0,83,40,1,0,0,0,117,45,0,0,0,82,101, - 116,117,114,110,32,116,104,101,32,99,111,100,101,32,111,98, - 106,101,99,116,32,102,111,114,32,116,104,101,32,102,114,111, - 122,101,110,32,109,111,100,117,108,101,46,40,2,0,0,0, - 117,4,0,0,0,95,105,109,112,117,17,0,0,0,103,101, - 116,95,102,114,111,122,101,110,95,111,98,106,101,99,116,40, - 2,0,0,0,117,3,0,0,0,99,108,115,117,8,0,0, - 0,102,117,108,108,110,97,109,101,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,8,0,0,0,103,101,116,95,99,111, - 100,101,108,1,0,0,115,2,0,0,0,0,4,117,23,0, - 0,0,70,114,111,122,101,110,73,109,112,111,114,116,101,114, - 46,103,101,116,95,99,111,100,101,99,2,0,0,0,0,0, - 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, - 0,0,0,100,1,0,83,40,2,0,0,0,117,54,0,0, - 0,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, - 102,114,111,122,101,110,32,109,111,100,117,108,101,115,32,100, - 111,32,110,111,116,32,104,97,118,101,32,115,111,117,114,99, - 101,32,99,111,100,101,46,78,40,1,0,0,0,117,4,0, - 0,0,78,111,110,101,40,2,0,0,0,117,3,0,0,0, - 99,108,115,117,8,0,0,0,102,117,108,108,110,97,109,101, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, - 0,103,101,116,95,115,111,117,114,99,101,114,1,0,0,115, - 2,0,0,0,0,4,117,25,0,0,0,70,114,111,122,101, - 110,73,109,112,111,114,116,101,114,46,103,101,116,95,115,111, - 117,114,99,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,2,0,0,0,67,0,0,0,115,13,0,0,0,116,0, - 0,106,1,0,124,1,0,131,1,0,83,40,1,0,0,0, - 117,41,0,0,0,82,101,116,117,114,110,32,105,102,32,116, - 104,101,32,102,114,111,122,101,110,32,109,111,100,117,108,101, - 32,105,115,32,97,32,112,97,99,107,97,103,101,46,40,2, - 0,0,0,117,4,0,0,0,95,105,109,112,117,17,0,0, - 0,105,115,95,102,114,111,122,101,110,95,112,97,99,107,97, - 103,101,40,2,0,0,0,117,3,0,0,0,99,108,115,117, + 111,116,115,116,114,97,112,62,117,8,0,0,0,103,101,116, + 95,99,111,100,101,129,2,0,0,115,18,0,0,0,0,1, + 15,1,15,1,24,1,15,1,15,1,13,1,4,2,18,1, + 117,30,0,0,0,95,83,111,117,114,99,101,108,101,115,115, + 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,99, + 111,100,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,0, + 83,40,2,0,0,0,117,39,0,0,0,82,101,116,117,114, + 110,32,78,111,110,101,32,97,115,32,116,104,101,114,101,32, + 105,115,32,110,111,32,115,111,117,114,99,101,32,99,111,100, + 101,46,78,40,1,0,0,0,117,4,0,0,0,78,111,110, + 101,40,2,0,0,0,117,4,0,0,0,115,101,108,102,117, 8,0,0,0,102,117,108,108,110,97,109,101,40,0,0,0, 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, - 111,116,115,116,114,97,112,62,117,10,0,0,0,105,115,95, - 112,97,99,107,97,103,101,120,1,0,0,115,2,0,0,0, - 0,4,117,25,0,0,0,70,114,111,122,101,110,73,109,112, - 111,114,116,101,114,46,105,115,95,112,97,99,107,97,103,101, - 78,40,14,0,0,0,117,8,0,0,0,95,95,110,97,109, - 101,95,95,117,10,0,0,0,95,95,109,111,100,117,108,101, - 95,95,117,12,0,0,0,95,95,113,117,97,108,110,97,109, - 101,95,95,117,7,0,0,0,95,95,100,111,99,95,95,117, - 11,0,0,0,99,108,97,115,115,109,101,116,104,111,100,117, - 4,0,0,0,78,111,110,101,117,11,0,0,0,102,105,110, - 100,95,109,111,100,117,108,101,117,11,0,0,0,115,101,116, - 95,112,97,99,107,97,103,101,117,10,0,0,0,115,101,116, - 95,108,111,97,100,101,114,117,16,0,0,0,95,114,101,113, - 117,105,114,101,115,95,102,114,111,122,101,110,117,11,0,0, - 0,108,111,97,100,95,109,111,100,117,108,101,117,8,0,0, - 0,103,101,116,95,99,111,100,101,117,10,0,0,0,103,101, - 116,95,115,111,117,114,99,101,117,10,0,0,0,105,115,95, - 112,97,99,107,97,103,101,40,1,0,0,0,117,10,0,0, - 0,95,95,108,111,99,97,108,115,95,95,40,0,0,0,0, - 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, - 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, - 116,115,116,114,97,112,62,117,14,0,0,0,70,114,111,122, - 101,110,73,109,112,111,114,116,101,114,80,1,0,0,115,26, - 0,0,0,16,7,6,2,3,1,18,4,3,1,3,1,3, - 1,27,11,3,1,21,5,3,1,21,5,3,1,117,14,0, - 0,0,70,114,111,122,101,110,73,109,112,111,114,116,101,114, - 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, - 0,66,0,0,0,115,74,0,0,0,124,0,0,69,101,0, - 0,90,1,0,100,0,0,90,2,0,100,1,0,90,3,0, - 100,2,0,100,3,0,132,0,0,90,4,0,100,4,0,100, - 5,0,132,0,0,90,5,0,101,6,0,100,6,0,100,10, - 0,100,7,0,100,8,0,132,0,1,131,1,0,90,8,0, - 100,9,0,83,40,11,0,0,0,117,13,0,0,0,95,76, - 111,97,100,101,114,66,97,115,105,99,115,117,84,0,0,0, - 66,97,115,101,32,99,108,97,115,115,32,111,102,32,99,111, - 109,109,111,110,32,99,111,100,101,32,110,101,101,100,101,100, - 32,98,121,32,98,111,116,104,32,83,111,117,114,99,101,76, - 111,97,100,101,114,32,97,110,100,10,32,32,32,32,95,83, - 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, - 100,101,114,46,99,2,0,0,0,0,0,0,0,3,0,0, - 0,3,0,0,0,67,0,0,0,115,54,0,0,0,124,0, - 0,106,0,0,124,1,0,131,1,0,106,1,0,116,2,0, - 131,1,0,100,1,0,25,125,2,0,124,2,0,106,3,0, - 100,2,0,100,3,0,131,2,0,100,4,0,25,100,5,0, - 107,2,0,83,40,6,0,0,0,117,141,0,0,0,67,111, - 110,99,114,101,116,101,32,105,109,112,108,101,109,101,110,116, - 97,116,105,111,110,32,111,102,32,73,110,115,112,101,99,116, - 76,111,97,100,101,114,46,105,115,95,112,97,99,107,97,103, - 101,32,98,121,32,99,104,101,99,107,105,110,103,32,105,102, - 10,32,32,32,32,32,32,32,32,116,104,101,32,112,97,116, - 104,32,114,101,116,117,114,110,101,100,32,98,121,32,103,101, - 116,95,102,105,108,101,110,97,109,101,32,104,97,115,32,97, - 32,102,105,108,101,110,97,109,101,32,111,102,32,39,95,95, - 105,110,105,116,95,95,46,112,121,39,46,105,2,0,0,0, - 117,1,0,0,0,46,105,1,0,0,0,105,0,0,0,0, - 117,8,0,0,0,95,95,105,110,105,116,95,95,40,4,0, - 0,0,117,12,0,0,0,103,101,116,95,102,105,108,101,110, - 97,109,101,117,10,0,0,0,114,112,97,114,116,105,116,105, - 111,110,117,8,0,0,0,112,97,116,104,95,115,101,112,117, - 6,0,0,0,114,115,112,108,105,116,40,3,0,0,0,117, - 4,0,0,0,115,101,108,102,117,8,0,0,0,102,117,108, - 108,110,97,109,101,117,8,0,0,0,102,105,108,101,110,97, - 109,101,40,0,0,0,0,40,0,0,0,0,117,29,0,0, - 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,10, - 0,0,0,105,115,95,112,97,99,107,97,103,101,132,1,0, - 0,115,4,0,0,0,0,3,28,1,117,24,0,0,0,95, - 76,111,97,100,101,114,66,97,115,105,99,115,46,105,115,95, - 112,97,99,107,97,103,101,99,5,0,0,0,0,0,0,0, - 11,0,0,0,23,0,0,0,67,0,0,0,115,213,1,0, - 0,124,2,0,100,1,0,100,2,0,133,2,0,25,125,5, - 0,124,2,0,100,2,0,100,3,0,133,2,0,25,125,6, - 0,124,2,0,100,3,0,100,4,0,133,2,0,25,125,7, - 0,116,0,0,124,5,0,131,1,0,100,2,0,107,3,0, - 115,84,0,124,5,0,116,1,0,106,2,0,131,0,0,107, - 3,0,114,120,0,116,3,0,100,5,0,106,4,0,124,1, - 0,131,1,0,100,6,0,124,1,0,100,7,0,124,3,0, - 131,1,2,130,1,0,110,116,0,116,0,0,124,6,0,131, - 1,0,100,2,0,107,3,0,114,178,0,100,8,0,106,4, - 0,124,1,0,131,1,0,125,8,0,116,5,0,124,8,0, - 131,1,0,1,116,6,0,124,8,0,131,1,0,130,1,0, - 110,58,0,116,0,0,124,7,0,131,1,0,100,2,0,107, - 3,0,114,236,0,100,9,0,106,4,0,124,1,0,131,1, - 0,125,8,0,116,5,0,124,8,0,131,1,0,1,116,6, - 0,124,8,0,131,1,0,130,1,0,110,0,0,124,4,0, - 100,1,0,107,9,0,114,199,1,121,20,0,116,8,0,124, - 4,0,100,10,0,25,131,1,0,125,9,0,87,110,18,0, - 4,116,9,0,107,10,0,114,32,1,1,1,1,89,110,71, - 0,88,116,10,0,124,6,0,131,1,0,124,9,0,107,3, - 0,114,103,1,100,11,0,106,4,0,124,1,0,131,1,0, - 125,8,0,116,5,0,124,8,0,131,1,0,1,116,3,0, - 124,8,0,100,6,0,124,1,0,100,7,0,124,3,0,131, - 1,2,130,1,0,110,0,0,121,18,0,124,4,0,100,12, - 0,25,100,13,0,64,125,10,0,87,110,18,0,4,116,9, - 0,107,10,0,114,141,1,1,1,1,89,113,199,1,88,116, - 10,0,124,7,0,131,1,0,124,10,0,107,3,0,114,199, - 1,116,3,0,100,11,0,106,4,0,124,1,0,131,1,0, - 100,6,0,124,1,0,100,7,0,124,3,0,131,1,2,130, - 1,0,113,199,1,110,0,0,124,2,0,100,4,0,100,1, - 0,133,2,0,25,83,40,14,0,0,0,117,193,0,0,0, - 82,101,116,117,114,110,32,116,104,101,32,109,97,114,115,104, - 97,108,108,101,100,32,98,121,116,101,115,32,102,114,111,109, - 32,98,121,116,101,99,111,100,101,44,32,118,101,114,105,102, - 121,105,110,103,32,116,104,101,32,109,97,103,105,99,10,32, - 32,32,32,32,32,32,32,110,117,109,98,101,114,44,32,116, - 105,109,101,115,116,97,109,112,32,97,110,100,32,115,111,117, - 114,99,101,32,115,105,122,101,32,97,108,111,110,103,32,116, - 104,101,32,119,97,121,46,10,10,32,32,32,32,32,32,32, - 32,73,102,32,115,111,117,114,99,101,95,115,116,97,116,115, - 32,105,115,32,78,111,110,101,32,116,104,101,110,32,115,107, - 105,112,32,116,104,101,32,116,105,109,101,115,116,97,109,112, - 32,99,104,101,99,107,46,10,10,32,32,32,32,32,32,32, - 32,78,105,4,0,0,0,105,8,0,0,0,105,12,0,0, - 0,117,22,0,0,0,98,97,100,32,109,97,103,105,99,32, - 110,117,109,98,101,114,32,105,110,32,123,125,117,4,0,0, - 0,110,97,109,101,117,4,0,0,0,112,97,116,104,117,19, - 0,0,0,98,97,100,32,116,105,109,101,115,116,97,109,112, - 32,105,110,32,123,125,117,14,0,0,0,98,97,100,32,115, - 105,122,101,32,105,110,32,123,125,117,5,0,0,0,109,116, - 105,109,101,117,24,0,0,0,98,121,116,101,99,111,100,101, - 32,105,115,32,115,116,97,108,101,32,102,111,114,32,123,125, - 117,4,0,0,0,115,105,122,101,73,255,255,255,255,0,0, - 0,0,40,11,0,0,0,117,3,0,0,0,108,101,110,117, - 4,0,0,0,95,105,109,112,117,9,0,0,0,103,101,116, - 95,109,97,103,105,99,117,11,0,0,0,73,109,112,111,114, - 116,69,114,114,111,114,117,6,0,0,0,102,111,114,109,97, - 116,117,15,0,0,0,118,101,114,98,111,115,101,95,109,101, - 115,115,97,103,101,117,8,0,0,0,69,79,70,69,114,114, - 111,114,117,4,0,0,0,78,111,110,101,117,3,0,0,0, - 105,110,116,117,8,0,0,0,75,101,121,69,114,114,111,114, - 117,7,0,0,0,95,114,95,108,111,110,103,40,11,0,0, - 0,117,4,0,0,0,115,101,108,102,117,8,0,0,0,102, - 117,108,108,110,97,109,101,117,4,0,0,0,100,97,116,97, - 117,13,0,0,0,98,121,116,101,99,111,100,101,95,112,97, - 116,104,117,12,0,0,0,115,111,117,114,99,101,95,115,116, - 97,116,115,117,5,0,0,0,109,97,103,105,99,117,13,0, - 0,0,114,97,119,95,116,105,109,101,115,116,97,109,112,117, - 8,0,0,0,114,97,119,95,115,105,122,101,117,7,0,0, - 0,109,101,115,115,97,103,101,117,12,0,0,0,115,111,117, - 114,99,101,95,109,116,105,109,101,117,11,0,0,0,115,111, - 117,114,99,101,95,115,105,122,101,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,20,0,0,0,95,98,121,116,101,115, - 95,102,114,111,109,95,98,121,116,101,99,111,100,101,138,1, - 0,0,115,66,0,0,0,0,7,16,1,16,1,16,1,36, - 1,18,1,18,1,18,1,15,1,10,1,15,1,18,1,15, - 1,10,1,15,1,12,1,3,1,20,1,13,1,5,2,18, - 1,15,1,10,1,15,1,12,1,3,1,18,1,13,1,5, - 2,18,1,3,1,15,1,21,3,117,34,0,0,0,95,76, - 111,97,100,101,114,66,97,115,105,99,115,46,95,98,121,116, - 101,115,95,102,114,111,109,95,98,121,116,101,99,111,100,101, - 117,10,0,0,0,115,111,117,114,99,101,108,101,115,115,99, - 2,0,0,0,1,0,0,0,5,0,0,0,3,0,0,0, - 67,0,0,0,115,196,0,0,0,124,1,0,106,0,0,125, - 3,0,124,0,0,106,1,0,124,3,0,131,1,0,125,4, - 0,124,0,0,106,2,0,124,3,0,131,1,0,124,1,0, - 95,3,0,124,2,0,115,72,0,116,4,0,106,5,0,124, - 1,0,106,3,0,131,1,0,124,1,0,95,6,0,110,12, - 0,124,1,0,106,3,0,124,1,0,95,6,0,124,3,0, - 124,1,0,95,7,0,124,0,0,106,8,0,124,3,0,131, - 1,0,114,142,0,124,1,0,106,3,0,106,9,0,116,10, - 0,100,1,0,131,2,0,100,2,0,25,103,1,0,124,1, - 0,95,11,0,110,25,0,124,1,0,106,7,0,106,12,0, - 100,3,0,131,1,0,100,2,0,25,124,1,0,95,7,0, - 124,0,0,124,1,0,95,13,0,116,14,0,124,4,0,124, - 1,0,106,15,0,131,2,0,1,124,1,0,83,40,4,0, - 0,0,117,82,0,0,0,72,101,108,112,101,114,32,102,111, - 114,32,108,111,97,100,95,109,111,100,117,108,101,32,97,98, - 108,101,32,116,111,32,104,97,110,100,108,101,32,101,105,116, - 104,101,114,32,115,111,117,114,99,101,32,111,114,32,115,111, - 117,114,99,101,108,101,115,115,10,32,32,32,32,32,32,32, - 32,108,111,97,100,105,110,103,46,105,1,0,0,0,105,0, - 0,0,0,117,1,0,0,0,46,40,16,0,0,0,117,8, - 0,0,0,95,95,110,97,109,101,95,95,117,8,0,0,0, - 103,101,116,95,99,111,100,101,117,12,0,0,0,103,101,116, - 95,102,105,108,101,110,97,109,101,117,8,0,0,0,95,95, - 102,105,108,101,95,95,117,4,0,0,0,95,105,109,112,117, - 17,0,0,0,99,97,99,104,101,95,102,114,111,109,95,115, - 111,117,114,99,101,117,10,0,0,0,95,95,99,97,99,104, - 101,100,95,95,117,11,0,0,0,95,95,112,97,99,107,97, - 103,101,95,95,117,10,0,0,0,105,115,95,112,97,99,107, - 97,103,101,117,6,0,0,0,114,115,112,108,105,116,117,8, - 0,0,0,112,97,116,104,95,115,101,112,117,8,0,0,0, - 95,95,112,97,116,104,95,95,117,10,0,0,0,114,112,97, - 114,116,105,116,105,111,110,117,10,0,0,0,95,95,108,111, - 97,100,101,114,95,95,117,4,0,0,0,101,120,101,99,117, - 8,0,0,0,95,95,100,105,99,116,95,95,40,5,0,0, - 0,117,4,0,0,0,115,101,108,102,117,6,0,0,0,109, - 111,100,117,108,101,117,10,0,0,0,115,111,117,114,99,101, - 108,101,115,115,117,4,0,0,0,110,97,109,101,117,11,0, - 0,0,99,111,100,101,95,111,98,106,101,99,116,40,0,0, - 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, - 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, - 111,111,116,115,116,114,97,112,62,117,12,0,0,0,95,108, - 111,97,100,95,109,111,100,117,108,101,183,1,0,0,115,26, - 0,0,0,0,4,9,1,15,1,18,1,6,1,24,2,12, - 1,9,1,15,1,34,2,25,1,9,1,16,1,117,26,0, - 0,0,95,76,111,97,100,101,114,66,97,115,105,99,115,46, - 95,108,111,97,100,95,109,111,100,117,108,101,78,70,40,9, - 0,0,0,117,8,0,0,0,95,95,110,97,109,101,95,95, - 117,10,0,0,0,95,95,109,111,100,117,108,101,95,95,117, - 12,0,0,0,95,95,113,117,97,108,110,97,109,101,95,95, - 117,7,0,0,0,95,95,100,111,99,95,95,117,10,0,0, - 0,105,115,95,112,97,99,107,97,103,101,117,20,0,0,0, - 95,98,121,116,101,115,95,102,114,111,109,95,98,121,116,101, - 99,111,100,101,117,17,0,0,0,109,111,100,117,108,101,95, - 102,111,114,95,108,111,97,100,101,114,117,5,0,0,0,70, - 97,108,115,101,117,12,0,0,0,95,108,111,97,100,95,109, - 111,100,117,108,101,40,1,0,0,0,117,10,0,0,0,95, - 95,108,111,99,97,108,115,95,95,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,13,0,0,0,95,76,111,97,100,101, - 114,66,97,115,105,99,115,127,1,0,0,115,10,0,0,0, - 16,3,6,2,12,6,12,45,6,1,117,13,0,0,0,95, - 76,111,97,100,101,114,66,97,115,105,99,115,99,1,0,0, - 0,0,0,0,0,1,0,0,0,2,0,0,0,66,0,0, - 0,115,92,0,0,0,124,0,0,69,101,0,0,90,1,0, - 100,0,0,90,2,0,100,1,0,100,2,0,132,0,0,90, - 3,0,100,3,0,100,4,0,132,0,0,90,4,0,100,5, - 0,100,6,0,132,0,0,90,5,0,100,7,0,100,8,0, - 132,0,0,90,6,0,100,9,0,100,10,0,132,0,0,90, - 7,0,100,11,0,100,12,0,132,0,0,90,8,0,100,13, - 0,83,40,14,0,0,0,117,12,0,0,0,83,111,117,114, - 99,101,76,111,97,100,101,114,99,2,0,0,0,0,0,0, - 0,2,0,0,0,1,0,0,0,67,0,0,0,115,10,0, - 0,0,116,0,0,130,1,0,100,1,0,83,40,2,0,0, - 0,117,121,0,0,0,79,112,116,105,111,110,97,108,32,109, - 101,116,104,111,100,32,116,104,97,116,32,114,101,116,117,114, - 110,115,32,116,104,101,32,109,111,100,105,102,105,99,97,116, - 105,111,110,32,116,105,109,101,32,40,97,110,32,105,110,116, - 41,32,102,111,114,32,116,104,101,10,32,32,32,32,32,32, - 32,32,115,112,101,99,105,102,105,101,100,32,112,97,116,104, - 44,32,119,104,101,114,101,32,112,97,116,104,32,105,115,32, - 97,32,115,116,114,46,10,32,32,32,32,32,32,32,32,78, - 40,1,0,0,0,117,19,0,0,0,78,111,116,73,109,112, - 108,101,109,101,110,116,101,100,69,114,114,111,114,40,2,0, - 0,0,117,4,0,0,0,115,101,108,102,117,4,0,0,0, - 112,97,116,104,40,0,0,0,0,40,0,0,0,0,117,29, - 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,10,0,0,0,112,97,116,104,95,109,116,105,109,101,206, - 1,0,0,115,2,0,0,0,0,4,117,23,0,0,0,83, - 111,117,114,99,101,76,111,97,100,101,114,46,112,97,116,104, - 95,109,116,105,109,101,99,2,0,0,0,0,0,0,0,2, - 0,0,0,3,0,0,0,67,0,0,0,115,20,0,0,0, - 105,1,0,124,0,0,106,0,0,124,1,0,131,1,0,100, - 1,0,54,83,40,2,0,0,0,117,114,1,0,0,79,112, - 116,105,111,110,97,108,32,109,101,116,104,111,100,32,114,101, - 116,117,114,110,105,110,103,32,97,32,109,101,116,97,100,97, - 116,97,32,100,105,99,116,32,102,111,114,32,116,104,101,32, - 115,112,101,99,105,102,105,101,100,32,112,97,116,104,10,32, - 32,32,32,32,32,32,32,116,111,32,98,121,32,116,104,101, - 32,112,97,116,104,32,40,115,116,114,41,46,10,32,32,32, - 32,32,32,32,32,80,111,115,115,105,98,108,101,32,107,101, - 121,115,58,10,32,32,32,32,32,32,32,32,45,32,39,109, - 116,105,109,101,39,32,40,109,97,110,100,97,116,111,114,121, - 41,32,105,115,32,116,104,101,32,110,117,109,101,114,105,99, - 32,116,105,109,101,115,116,97,109,112,32,111,102,32,108,97, - 115,116,32,115,111,117,114,99,101,10,32,32,32,32,32,32, - 32,32,32,32,99,111,100,101,32,109,111,100,105,102,105,99, - 97,116,105,111,110,59,10,32,32,32,32,32,32,32,32,45, - 32,39,115,105,122,101,39,32,40,111,112,116,105,111,110,97, - 108,41,32,105,115,32,116,104,101,32,115,105,122,101,32,105, - 110,32,98,121,116,101,115,32,111,102,32,116,104,101,32,115, - 111,117,114,99,101,32,99,111,100,101,46,10,10,32,32,32, - 32,32,32,32,32,73,109,112,108,101,109,101,110,116,105,110, - 103,32,116,104,105,115,32,109,101,116,104,111,100,32,97,108, - 108,111,119,115,32,116,104,101,32,108,111,97,100,101,114,32, - 116,111,32,114,101,97,100,32,98,121,116,101,99,111,100,101, - 32,102,105,108,101,115,46,10,32,32,32,32,32,32,32,32, - 117,5,0,0,0,109,116,105,109,101,40,1,0,0,0,117, - 10,0,0,0,112,97,116,104,95,109,116,105,109,101,40,2, - 0,0,0,117,4,0,0,0,115,101,108,102,117,4,0,0, - 0,112,97,116,104,40,0,0,0,0,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,10,0,0,0,112,97,116,104,95,115,116,97,116,115, - 212,1,0,0,115,2,0,0,0,0,10,117,23,0,0,0, - 83,111,117,114,99,101,76,111,97,100,101,114,46,112,97,116, - 104,95,115,116,97,116,115,99,3,0,0,0,0,0,0,0, - 3,0,0,0,1,0,0,0,67,0,0,0,115,10,0,0, - 0,116,0,0,130,1,0,100,1,0,83,40,2,0,0,0, - 117,151,0,0,0,79,112,116,105,111,110,97,108,32,109,101, - 116,104,111,100,32,119,104,105,99,104,32,119,114,105,116,101, - 115,32,100,97,116,97,32,40,98,121,116,101,115,41,32,116, - 111,32,97,32,102,105,108,101,32,112,97,116,104,32,40,97, - 32,115,116,114,41,46,10,10,32,32,32,32,32,32,32,32, - 73,109,112,108,101,109,101,110,116,105,110,103,32,116,104,105, - 115,32,109,101,116,104,111,100,32,97,108,108,111,119,115,32, - 102,111,114,32,116,104,101,32,119,114,105,116,105,110,103,32, - 111,102,32,98,121,116,101,99,111,100,101,32,102,105,108,101, - 115,46,10,10,32,32,32,32,32,32,32,32,78,40,1,0, - 0,0,117,19,0,0,0,78,111,116,73,109,112,108,101,109, - 101,110,116,101,100,69,114,114,111,114,40,3,0,0,0,117, - 4,0,0,0,115,101,108,102,117,4,0,0,0,112,97,116, - 104,117,4,0,0,0,100,97,116,97,40,0,0,0,0,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,8,0,0,0,115,101,116,95,100, - 97,116,97,224,1,0,0,115,2,0,0,0,0,6,117,21, - 0,0,0,83,111,117,114,99,101,76,111,97,100,101,114,46, - 115,101,116,95,100,97,116,97,99,2,0,0,0,0,0,0, - 0,7,0,0,0,12,0,0,0,67,0,0,0,115,156,0, - 0,0,100,1,0,100,2,0,108,0,0,125,2,0,124,0, - 0,106,1,0,124,1,0,131,1,0,125,3,0,121,19,0, - 124,0,0,106,2,0,124,3,0,131,1,0,125,4,0,87, - 110,36,0,4,116,3,0,107,10,0,114,84,0,1,1,1, - 116,4,0,100,3,0,100,4,0,124,1,0,131,1,1,130, - 1,0,89,110,1,0,88,124,2,0,106,5,0,116,6,0, - 106,7,0,124,4,0,131,1,0,106,8,0,131,1,0,125, - 5,0,116,6,0,106,9,0,100,2,0,100,5,0,131,2, - 0,125,6,0,124,6,0,106,12,0,124,4,0,106,12,0, - 124,5,0,100,1,0,25,131,1,0,131,1,0,83,40,6, - 0,0,0,117,52,0,0,0,67,111,110,99,114,101,116,101, - 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, - 111,102,32,73,110,115,112,101,99,116,76,111,97,100,101,114, - 46,103,101,116,95,115,111,117,114,99,101,46,105,0,0,0, - 0,78,117,39,0,0,0,115,111,117,114,99,101,32,110,111, - 116,32,97,118,97,105,108,97,98,108,101,32,116,104,114,111, - 117,103,104,32,103,101,116,95,100,97,116,97,40,41,117,4, - 0,0,0,110,97,109,101,84,40,13,0,0,0,117,8,0, - 0,0,116,111,107,101,110,105,122,101,117,12,0,0,0,103, - 101,116,95,102,105,108,101,110,97,109,101,117,8,0,0,0, - 103,101,116,95,100,97,116,97,117,7,0,0,0,73,79,69, - 114,114,111,114,117,11,0,0,0,73,109,112,111,114,116,69, - 114,114,111,114,117,15,0,0,0,100,101,116,101,99,116,95, - 101,110,99,111,100,105,110,103,117,3,0,0,0,95,105,111, - 117,7,0,0,0,66,121,116,101,115,73,79,117,8,0,0, - 0,114,101,97,100,108,105,110,101,117,25,0,0,0,73,110, - 99,114,101,109,101,110,116,97,108,78,101,119,108,105,110,101, - 68,101,99,111,100,101,114,117,4,0,0,0,78,111,110,101, - 117,4,0,0,0,84,114,117,101,117,6,0,0,0,100,101, - 99,111,100,101,40,7,0,0,0,117,4,0,0,0,115,101, - 108,102,117,8,0,0,0,102,117,108,108,110,97,109,101,117, - 8,0,0,0,116,111,107,101,110,105,122,101,117,4,0,0, - 0,112,97,116,104,117,12,0,0,0,115,111,117,114,99,101, - 95,98,121,116,101,115,117,8,0,0,0,101,110,99,111,100, - 105,110,103,117,15,0,0,0,110,101,119,108,105,110,101,95, - 100,101,99,111,100,101,114,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,10,0,0,0,103,101,116,95,115,111,117,114, - 99,101,233,1,0,0,115,20,0,0,0,0,2,12,1,15, - 1,3,1,19,1,13,1,9,1,14,1,27,1,18,1,117, - 23,0,0,0,83,111,117,114,99,101,76,111,97,100,101,114, - 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, - 0,0,0,0,12,0,0,0,37,0,0,0,67,0,0,0, - 115,39,2,0,0,124,0,0,106,0,0,124,1,0,131,1, - 0,125,2,0,116,1,0,106,2,0,124,2,0,131,1,0, - 125,3,0,100,10,0,125,4,0,124,3,0,100,10,0,107, - 9,0,114,64,1,121,19,0,124,0,0,106,4,0,124,2, - 0,131,1,0,125,5,0,87,110,18,0,4,116,5,0,107, - 10,0,114,87,0,1,1,1,89,113,64,1,88,116,6,0, - 124,5,0,100,1,0,25,131,1,0,125,4,0,121,19,0, - 124,0,0,106,7,0,124,3,0,131,1,0,125,6,0,87, - 110,18,0,4,116,8,0,107,10,0,114,143,0,1,1,1, - 89,113,64,1,88,121,28,0,124,0,0,106,9,0,124,1, - 0,124,6,0,124,3,0,124,5,0,131,4,0,125,7,0, - 87,110,24,0,4,116,10,0,116,11,0,102,2,0,107,10, - 0,114,198,0,1,1,1,89,113,64,1,88,116,12,0,100, - 2,0,124,3,0,124,2,0,131,3,0,1,116,13,0,106, - 14,0,124,7,0,131,1,0,125,8,0,116,15,0,124,8, - 0,116,16,0,131,2,0,114,22,1,116,1,0,106,17,0, - 124,8,0,124,2,0,131,2,0,1,116,12,0,100,3,0, - 124,3,0,131,2,0,1,124,8,0,83,100,4,0,125,9, - 0,116,10,0,124,9,0,106,18,0,124,3,0,131,1,0, - 100,5,0,124,1,0,100,6,0,124,3,0,131,1,2,130, - 1,0,110,0,0,124,0,0,106,7,0,124,2,0,131,1, - 0,125,10,0,116,19,0,124,10,0,124,2,0,100,7,0, - 100,8,0,100,11,0,131,3,1,125,11,0,116,12,0,100, - 3,0,124,2,0,131,2,0,1,116,21,0,106,22,0,12, - 114,35,2,124,3,0,100,10,0,107,9,0,114,35,2,124, - 4,0,100,10,0,107,9,0,114,35,2,116,23,0,116,1, - 0,106,24,0,131,0,0,131,1,0,125,6,0,124,6,0, - 106,25,0,116,26,0,124,4,0,131,1,0,131,1,0,1, - 124,6,0,106,25,0,116,26,0,116,27,0,124,10,0,131, - 1,0,131,1,0,131,1,0,1,124,6,0,106,25,0,116, - 13,0,106,28,0,124,11,0,131,1,0,131,1,0,1,121, - 33,0,124,0,0,106,29,0,124,3,0,124,6,0,131,2, - 0,1,116,12,0,100,9,0,124,3,0,131,2,0,1,87, - 113,35,2,4,116,5,0,107,10,0,114,31,2,1,1,1, - 89,113,35,2,88,110,0,0,124,11,0,83,40,12,0,0, - 0,117,190,0,0,0,67,111,110,99,114,101,116,101,32,105, - 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, - 32,73,110,115,112,101,99,116,76,111,97,100,101,114,46,103, - 101,116,95,99,111,100,101,46,10,10,32,32,32,32,32,32, - 32,32,82,101,97,100,105,110,103,32,111,102,32,98,121,116, - 101,99,111,100,101,32,114,101,113,117,105,114,101,115,32,112, - 97,116,104,95,115,116,97,116,115,32,116,111,32,98,101,32, - 105,109,112,108,101,109,101,110,116,101,100,46,32,84,111,32, - 119,114,105,116,101,10,32,32,32,32,32,32,32,32,98,121, - 116,101,99,111,100,101,44,32,115,101,116,95,100,97,116,97, - 32,109,117,115,116,32,97,108,115,111,32,98,101,32,105,109, - 112,108,101,109,101,110,116,101,100,46,10,10,32,32,32,32, - 32,32,32,32,117,5,0,0,0,109,116,105,109,101,117,13, - 0,0,0,123,125,32,109,97,116,99,104,101,115,32,123,125, - 117,19,0,0,0,99,111,100,101,32,111,98,106,101,99,116, - 32,102,114,111,109,32,123,125,117,21,0,0,0,78,111,110, - 45,99,111,100,101,32,111,98,106,101,99,116,32,105,110,32, - 123,125,117,4,0,0,0,110,97,109,101,117,4,0,0,0, - 112,97,116,104,117,4,0,0,0,101,120,101,99,117,12,0, - 0,0,100,111,110,116,95,105,110,104,101,114,105,116,117,10, - 0,0,0,119,114,111,116,101,32,123,33,114,125,78,84,40, - 30,0,0,0,117,12,0,0,0,103,101,116,95,102,105,108, - 101,110,97,109,101,117,4,0,0,0,95,105,109,112,117,17, - 0,0,0,99,97,99,104,101,95,102,114,111,109,95,115,111, - 117,114,99,101,117,4,0,0,0,78,111,110,101,117,10,0, - 0,0,112,97,116,104,95,115,116,97,116,115,117,19,0,0, - 0,78,111,116,73,109,112,108,101,109,101,110,116,101,100,69, - 114,114,111,114,117,3,0,0,0,105,110,116,117,8,0,0, - 0,103,101,116,95,100,97,116,97,117,7,0,0,0,73,79, - 69,114,114,111,114,117,20,0,0,0,95,98,121,116,101,115, - 95,102,114,111,109,95,98,121,116,101,99,111,100,101,117,11, - 0,0,0,73,109,112,111,114,116,69,114,114,111,114,117,8, - 0,0,0,69,79,70,69,114,114,111,114,117,15,0,0,0, - 118,101,114,98,111,115,101,95,109,101,115,115,97,103,101,117, - 7,0,0,0,109,97,114,115,104,97,108,117,5,0,0,0, - 108,111,97,100,115,117,10,0,0,0,105,115,105,110,115,116, - 97,110,99,101,117,9,0,0,0,99,111,100,101,95,116,121, - 112,101,117,16,0,0,0,95,102,105,120,95,99,111,95,102, - 105,108,101,110,97,109,101,117,6,0,0,0,102,111,114,109, - 97,116,117,7,0,0,0,99,111,109,112,105,108,101,117,4, - 0,0,0,84,114,117,101,117,3,0,0,0,115,121,115,117, - 19,0,0,0,100,111,110,116,95,119,114,105,116,101,95,98, - 121,116,101,99,111,100,101,117,9,0,0,0,98,121,116,101, - 97,114,114,97,121,117,9,0,0,0,103,101,116,95,109,97, - 103,105,99,117,6,0,0,0,101,120,116,101,110,100,117,7, - 0,0,0,95,119,95,108,111,110,103,117,3,0,0,0,108, - 101,110,117,5,0,0,0,100,117,109,112,115,117,8,0,0, - 0,115,101,116,95,100,97,116,97,40,12,0,0,0,117,4, - 0,0,0,115,101,108,102,117,8,0,0,0,102,117,108,108, - 110,97,109,101,117,11,0,0,0,115,111,117,114,99,101,95, - 112,97,116,104,117,13,0,0,0,98,121,116,101,99,111,100, - 101,95,112,97,116,104,117,12,0,0,0,115,111,117,114,99, - 101,95,109,116,105,109,101,117,2,0,0,0,115,116,117,4, - 0,0,0,100,97,116,97,117,10,0,0,0,98,121,116,101, - 115,95,100,97,116,97,117,5,0,0,0,102,111,117,110,100, - 117,3,0,0,0,109,115,103,117,12,0,0,0,115,111,117, - 114,99,101,95,98,121,116,101,115,117,11,0,0,0,99,111, - 100,101,95,111,98,106,101,99,116,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,8,0,0,0,103,101,116,95,99,111, - 100,101,246,1,0,0,115,92,0,0,0,0,7,15,1,15, - 1,6,1,12,1,3,1,19,1,13,1,5,2,16,1,3, - 1,19,1,13,1,5,2,3,1,12,1,3,1,13,1,19, - 1,5,2,9,1,7,1,15,1,15,1,16,1,6,1,7, - 1,4,2,6,1,18,1,18,1,15,1,15,1,9,1,13, - 1,22,1,12,4,18,1,19,1,25,1,22,1,3,1,16, - 1,17,1,13,1,8,1,117,21,0,0,0,83,111,117,114, - 99,101,76,111,97,100,101,114,46,103,101,116,95,99,111,100, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,2,0, - 0,0,67,0,0,0,115,13,0,0,0,124,0,0,106,0, - 0,124,1,0,131,1,0,83,40,1,0,0,0,117,0,1, - 0,0,67,111,110,99,114,101,116,101,32,105,109,112,108,101, - 109,101,110,116,97,116,105,111,110,32,111,102,32,76,111,97, - 100,101,114,46,108,111,97,100,95,109,111,100,117,108,101,46, - 10,10,32,32,32,32,32,32,32,32,82,101,113,117,105,114, - 101,115,32,69,120,101,99,117,116,105,111,110,76,111,97,100, - 101,114,46,103,101,116,95,102,105,108,101,110,97,109,101,32, - 97,110,100,32,82,101,115,111,117,114,99,101,76,111,97,100, - 101,114,46,103,101,116,95,100,97,116,97,32,116,111,32,98, - 101,10,32,32,32,32,32,32,32,32,105,109,112,108,101,109, - 101,110,116,101,100,32,116,111,32,108,111,97,100,32,115,111, - 117,114,99,101,32,99,111,100,101,46,32,85,115,101,32,111, - 102,32,98,121,116,101,99,111,100,101,32,105,115,32,100,105, - 99,116,97,116,101,100,32,98,121,32,119,104,101,116,104,101, - 114,10,32,32,32,32,32,32,32,32,103,101,116,95,99,111, - 100,101,32,117,115,101,115,47,119,114,105,116,101,115,32,98, - 121,116,101,99,111,100,101,46,10,10,32,32,32,32,32,32, - 32,32,40,1,0,0,0,117,12,0,0,0,95,108,111,97, - 100,95,109,111,100,117,108,101,40,2,0,0,0,117,4,0, - 0,0,115,101,108,102,117,8,0,0,0,102,117,108,108,110, - 97,109,101,40,0,0,0,0,40,0,0,0,0,117,29,0, - 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, - 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 11,0,0,0,108,111,97,100,95,109,111,100,117,108,101,51, - 2,0,0,115,2,0,0,0,0,8,117,24,0,0,0,83, - 111,117,114,99,101,76,111,97,100,101,114,46,108,111,97,100, - 95,109,111,100,117,108,101,78,40,9,0,0,0,117,8,0, + 111,116,115,116,114,97,112,62,117,10,0,0,0,103,101,116, + 95,115,111,117,114,99,101,141,2,0,0,115,2,0,0,0, + 0,2,117,32,0,0,0,95,83,111,117,114,99,101,108,101, + 115,115,70,105,108,101,76,111,97,100,101,114,46,103,101,116, + 95,115,111,117,114,99,101,78,40,7,0,0,0,117,8,0, 0,0,95,95,110,97,109,101,95,95,117,10,0,0,0,95, 95,109,111,100,117,108,101,95,95,117,12,0,0,0,95,95, - 113,117,97,108,110,97,109,101,95,95,117,10,0,0,0,112, - 97,116,104,95,109,116,105,109,101,117,10,0,0,0,112,97, - 116,104,95,115,116,97,116,115,117,8,0,0,0,115,101,116, - 95,100,97,116,97,117,10,0,0,0,103,101,116,95,115,111, - 117,114,99,101,117,8,0,0,0,103,101,116,95,99,111,100, - 101,117,11,0,0,0,108,111,97,100,95,109,111,100,117,108, - 101,40,1,0,0,0,117,10,0,0,0,95,95,108,111,99, - 97,108,115,95,95,40,0,0,0,0,40,0,0,0,0,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,12,0,0,0,83,111,117,114,99,101,76,111,97,100, - 101,114,204,1,0,0,115,12,0,0,0,16,2,12,6,12, - 12,12,9,12,13,12,61,117,12,0,0,0,83,111,117,114, - 99,101,76,111,97,100,101,114,99,1,0,0,0,0,0,0, - 0,1,0,0,0,3,0,0,0,66,0,0,0,115,68,0, - 0,0,124,0,0,69,101,0,0,90,1,0,100,0,0,90, - 2,0,100,1,0,90,3,0,100,2,0,100,3,0,132,0, - 0,90,4,0,101,5,0,100,4,0,100,5,0,132,0,0, - 131,1,0,90,6,0,100,6,0,100,7,0,132,0,0,90, - 7,0,100,8,0,83,40,9,0,0,0,117,11,0,0,0, - 95,70,105,108,101,76,111,97,100,101,114,117,103,0,0,0, - 66,97,115,101,32,102,105,108,101,32,108,111,97,100,101,114, - 32,99,108,97,115,115,32,119,104,105,99,104,32,105,109,112, - 108,101,109,101,110,116,115,32,116,104,101,32,108,111,97,100, - 101,114,32,112,114,111,116,111,99,111,108,32,109,101,116,104, - 111,100,115,32,116,104,97,116,10,32,32,32,32,114,101,113, - 117,105,114,101,32,102,105,108,101,32,115,121,115,116,101,109, - 32,117,115,97,103,101,46,99,3,0,0,0,0,0,0,0, - 3,0,0,0,2,0,0,0,67,0,0,0,115,22,0,0, - 0,124,1,0,124,0,0,95,0,0,124,2,0,124,0,0, - 95,1,0,100,1,0,83,40,2,0,0,0,117,75,0,0, - 0,67,97,99,104,101,32,116,104,101,32,109,111,100,117,108, - 101,32,110,97,109,101,32,97,110,100,32,116,104,101,32,112, - 97,116,104,32,116,111,32,116,104,101,32,102,105,108,101,32, - 102,111,117,110,100,32,98,121,32,116,104,101,10,32,32,32, - 32,32,32,32,32,102,105,110,100,101,114,46,78,40,2,0, - 0,0,117,5,0,0,0,95,110,97,109,101,117,5,0,0, - 0,95,112,97,116,104,40,3,0,0,0,117,4,0,0,0, - 115,101,108,102,117,8,0,0,0,102,117,108,108,110,97,109, + 113,117,97,108,110,97,109,101,95,95,117,7,0,0,0,95, + 95,100,111,99,95,95,117,11,0,0,0,108,111,97,100,95, + 109,111,100,117,108,101,117,8,0,0,0,103,101,116,95,99, + 111,100,101,117,10,0,0,0,103,101,116,95,115,111,117,114, + 99,101,40,1,0,0,0,117,10,0,0,0,95,95,108,111, + 99,97,108,115,95,95,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,21,0,0,0,95,83,111,117,114,99,101,108,101, + 115,115,70,105,108,101,76,111,97,100,101,114,122,2,0,0, + 115,8,0,0,0,16,2,6,2,12,3,12,12,117,21,0, + 0,0,95,83,111,117,114,99,101,108,101,115,115,70,105,108, + 101,76,111,97,100,101,114,99,1,0,0,0,0,0,0,0, + 1,0,0,0,5,0,0,0,66,0,0,0,115,122,0,0, + 0,124,0,0,69,101,0,0,90,1,0,100,0,0,90,2, + 0,100,1,0,90,3,0,100,2,0,100,3,0,132,0,0, + 90,4,0,101,5,0,101,6,0,101,7,0,100,4,0,100, + 5,0,132,0,0,131,1,0,131,1,0,131,1,0,90,8, + 0,101,5,0,100,6,0,100,7,0,132,0,0,131,1,0, + 90,9,0,101,5,0,100,8,0,100,9,0,132,0,0,131, + 1,0,90,10,0,101,5,0,100,10,0,100,11,0,132,0, + 0,131,1,0,90,11,0,100,12,0,83,40,13,0,0,0, + 117,20,0,0,0,95,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,117,93,0,0,0,76,111, + 97,100,101,114,32,102,111,114,32,101,120,116,101,110,115,105, + 111,110,32,109,111,100,117,108,101,115,46,10,10,32,32,32, + 32,84,104,101,32,99,111,110,115,116,114,117,99,116,111,114, + 32,105,115,32,100,101,115,105,103,110,101,100,32,116,111,32, + 119,111,114,107,32,119,105,116,104,32,70,105,108,101,70,105, + 110,100,101,114,46,10,10,32,32,32,32,99,3,0,0,0, + 0,0,0,0,3,0,0,0,2,0,0,0,67,0,0,0, + 115,22,0,0,0,124,1,0,124,0,0,95,0,0,124,2, + 0,124,0,0,95,1,0,100,0,0,83,40,1,0,0,0, + 78,40,2,0,0,0,117,5,0,0,0,95,110,97,109,101, + 117,5,0,0,0,95,112,97,116,104,40,3,0,0,0,117, + 4,0,0,0,115,101,108,102,117,4,0,0,0,110,97,109, 101,117,4,0,0,0,112,97,116,104,40,0,0,0,0,40, 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, 115,116,114,97,112,62,117,8,0,0,0,95,95,105,110,105, - 116,95,95,67,2,0,0,115,4,0,0,0,0,3,9,1, - 117,20,0,0,0,95,70,105,108,101,76,111,97,100,101,114, - 46,95,95,105,110,105,116,95,95,99,2,0,0,0,0,0, - 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,7, - 0,0,0,124,0,0,106,0,0,83,40,1,0,0,0,117, - 58,0,0,0,82,101,116,117,114,110,32,116,104,101,32,112, - 97,116,104,32,116,111,32,116,104,101,32,115,111,117,114,99, - 101,32,102,105,108,101,32,97,115,32,102,111,117,110,100,32, - 98,121,32,116,104,101,32,102,105,110,100,101,114,46,40,1, - 0,0,0,117,5,0,0,0,95,112,97,116,104,40,2,0, - 0,0,117,4,0,0,0,115,101,108,102,117,8,0,0,0, - 102,117,108,108,110,97,109,101,40,0,0,0,0,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,12,0,0,0,103,101,116,95,102,105,108, - 101,110,97,109,101,73,2,0,0,115,2,0,0,0,0,3, - 117,24,0,0,0,95,70,105,108,101,76,111,97,100,101,114, - 46,103,101,116,95,102,105,108,101,110,97,109,101,99,2,0, - 0,0,0,0,0,0,3,0,0,0,8,0,0,0,67,0, - 0,0,115,41,0,0,0,116,0,0,106,1,0,124,1,0, - 100,1,0,131,2,0,143,17,0,125,2,0,124,2,0,106, - 2,0,131,0,0,83,87,100,2,0,81,88,100,2,0,83, - 40,3,0,0,0,117,39,0,0,0,82,101,116,117,114,110, - 32,116,104,101,32,100,97,116,97,32,102,114,111,109,32,112, - 97,116,104,32,97,115,32,114,97,119,32,98,121,116,101,115, - 46,117,1,0,0,0,114,78,40,3,0,0,0,117,3,0, - 0,0,95,105,111,117,6,0,0,0,70,105,108,101,73,79, - 117,4,0,0,0,114,101,97,100,40,3,0,0,0,117,4, - 0,0,0,115,101,108,102,117,4,0,0,0,112,97,116,104, - 117,4,0,0,0,102,105,108,101,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,8,0,0,0,103,101,116,95,100,97, - 116,97,78,2,0,0,115,4,0,0,0,0,2,21,1,117, - 20,0,0,0,95,70,105,108,101,76,111,97,100,101,114,46, - 103,101,116,95,100,97,116,97,78,40,8,0,0,0,117,8, + 116,95,95,154,2,0,0,115,4,0,0,0,0,1,9,1, + 117,29,0,0,0,95,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,46,95,95,105,110,105,116, + 95,95,99,2,0,0,0,0,0,0,0,4,0,0,0,9, + 0,0,0,67,0,0,0,115,113,0,0,0,124,1,0,116, + 0,0,106,1,0,107,6,0,125,2,0,121,45,0,116,2, + 0,106,3,0,124,1,0,124,0,0,106,4,0,131,2,0, + 125,3,0,116,5,0,100,1,0,124,0,0,106,4,0,131, + 2,0,1,124,3,0,83,87,110,46,0,1,1,1,124,2, + 0,12,114,101,0,124,1,0,116,0,0,106,1,0,107,6, + 0,114,101,0,116,0,0,106,1,0,124,1,0,61,110,0, + 0,130,0,0,89,110,1,0,88,100,2,0,83,40,3,0, + 0,0,117,25,0,0,0,76,111,97,100,32,97,110,32,101, + 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,46, + 117,33,0,0,0,101,120,116,101,110,115,105,111,110,32,109, + 111,100,117,108,101,32,108,111,97,100,101,100,32,102,114,111, + 109,32,123,33,114,125,78,40,6,0,0,0,117,3,0,0, + 0,115,121,115,117,7,0,0,0,109,111,100,117,108,101,115, + 117,4,0,0,0,95,105,109,112,117,12,0,0,0,108,111, + 97,100,95,100,121,110,97,109,105,99,117,5,0,0,0,95, + 112,97,116,104,117,15,0,0,0,118,101,114,98,111,115,101, + 95,109,101,115,115,97,103,101,40,4,0,0,0,117,4,0, + 0,0,115,101,108,102,117,8,0,0,0,102,117,108,108,110, + 97,109,101,117,9,0,0,0,105,115,95,114,101,108,111,97, + 100,117,6,0,0,0,109,111,100,117,108,101,40,0,0,0, + 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,117,11,0,0,0,108,111,97, + 100,95,109,111,100,117,108,101,158,2,0,0,115,18,0,0, + 0,0,5,15,1,3,1,21,1,16,1,8,1,3,1,22, + 1,13,1,117,32,0,0,0,95,69,120,116,101,110,115,105, + 111,110,70,105,108,101,76,111,97,100,101,114,46,108,111,97, + 100,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,115,4,0, + 0,0,100,1,0,83,40,2,0,0,0,117,59,0,0,0, + 82,101,116,117,114,110,32,70,97,108,115,101,32,97,115,32, + 97,110,32,101,120,116,101,110,115,105,111,110,32,109,111,100, + 117,108,101,32,99,97,110,32,110,101,118,101,114,32,98,101, + 32,97,32,112,97,99,107,97,103,101,46,70,40,1,0,0, + 0,117,5,0,0,0,70,97,108,115,101,40,2,0,0,0, + 117,4,0,0,0,115,101,108,102,117,8,0,0,0,102,117, + 108,108,110,97,109,101,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,10,0,0,0,105,115,95,112,97,99,107,97,103, + 101,173,2,0,0,115,2,0,0,0,0,3,117,31,0,0, + 0,95,69,120,116,101,110,115,105,111,110,70,105,108,101,76, + 111,97,100,101,114,46,105,115,95,112,97,99,107,97,103,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,115,4,0,0,0,100,1,0,83,40,2, + 0,0,0,117,63,0,0,0,82,101,116,117,114,110,32,78, + 111,110,101,32,97,115,32,97,110,32,101,120,116,101,110,115, + 105,111,110,32,109,111,100,117,108,101,32,99,97,110,110,111, + 116,32,99,114,101,97,116,101,32,97,32,99,111,100,101,32, + 111,98,106,101,99,116,46,78,40,1,0,0,0,117,4,0, + 0,0,78,111,110,101,40,2,0,0,0,117,4,0,0,0, + 115,101,108,102,117,8,0,0,0,102,117,108,108,110,97,109, + 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, + 0,0,103,101,116,95,99,111,100,101,178,2,0,0,115,2, + 0,0,0,0,3,117,29,0,0,0,95,69,120,116,101,110, + 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,103, + 101,116,95,99,111,100,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, + 0,100,1,0,83,40,2,0,0,0,117,53,0,0,0,82, + 101,116,117,114,110,32,78,111,110,101,32,97,115,32,101,120, + 116,101,110,115,105,111,110,32,109,111,100,117,108,101,115,32, + 104,97,118,101,32,110,111,32,115,111,117,114,99,101,32,99, + 111,100,101,46,78,40,1,0,0,0,117,4,0,0,0,78, + 111,110,101,40,2,0,0,0,117,4,0,0,0,115,101,108, + 102,117,8,0,0,0,102,117,108,108,110,97,109,101,40,0, + 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,62,117,10,0,0,0,103, + 101,116,95,115,111,117,114,99,101,183,2,0,0,115,2,0, + 0,0,0,3,117,31,0,0,0,95,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,46,103,101, + 116,95,115,111,117,114,99,101,78,40,12,0,0,0,117,8, 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, 95,95,109,111,100,117,108,101,95,95,117,12,0,0,0,95, 95,113,117,97,108,110,97,109,101,95,95,117,7,0,0,0, 95,95,100,111,99,95,95,117,8,0,0,0,95,95,105,110, 105,116,95,95,117,11,0,0,0,95,99,104,101,99,107,95, - 110,97,109,101,117,12,0,0,0,103,101,116,95,102,105,108, - 101,110,97,109,101,117,8,0,0,0,103,101,116,95,100,97, - 116,97,40,1,0,0,0,117,10,0,0,0,95,95,108,111, - 99,97,108,115,95,95,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,11,0,0,0,95,70,105,108,101,76,111,97,100, - 101,114,62,2,0,0,115,8,0,0,0,16,3,6,2,12, - 6,18,5,117,11,0,0,0,95,70,105,108,101,76,111,97, - 100,101,114,99,1,0,0,0,0,0,0,0,1,0,0,0, - 2,0,0,0,66,0,0,0,115,50,0,0,0,124,0,0, - 69,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, - 90,3,0,100,2,0,100,3,0,132,0,0,90,4,0,100, - 4,0,100,5,0,132,0,0,90,5,0,100,6,0,83,40, - 7,0,0,0,117,17,0,0,0,95,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,117,62,0,0,0,67, - 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,32,111,102,32,83,111,117,114,99,101, - 76,111,97,100,101,114,32,117,115,105,110,103,32,116,104,101, - 32,102,105,108,101,32,115,121,115,116,101,109,46,99,2,0, - 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, - 0,0,115,39,0,0,0,116,0,0,106,1,0,124,1,0, - 131,1,0,125,2,0,105,2,0,124,2,0,106,2,0,100, - 1,0,54,124,2,0,106,3,0,100,2,0,54,83,40,3, - 0,0,0,117,32,0,0,0,82,101,116,117,114,110,32,116, - 104,101,32,109,101,116,97,100,97,116,32,102,111,114,32,116, - 104,101,32,112,97,116,104,46,117,5,0,0,0,109,116,105, - 109,101,117,4,0,0,0,115,105,122,101,40,4,0,0,0, - 117,3,0,0,0,95,111,115,117,4,0,0,0,115,116,97, - 116,117,8,0,0,0,115,116,95,109,116,105,109,101,117,7, - 0,0,0,115,116,95,115,105,122,101,40,3,0,0,0,117, - 4,0,0,0,115,101,108,102,117,4,0,0,0,112,97,116, - 104,117,2,0,0,0,115,116,40,0,0,0,0,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,10,0,0,0,112,97,116,104,95,115,116, - 97,116,115,88,2,0,0,115,4,0,0,0,0,2,15,1, - 117,28,0,0,0,95,83,111,117,114,99,101,70,105,108,101, - 76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,116, - 115,99,3,0,0,0,0,0,0,0,8,0,0,0,13,0, - 0,0,67,0,0,0,115,254,0,0,0,124,1,0,106,0, - 0,116,1,0,131,1,0,92,3,0,125,3,0,125,4,0, - 125,5,0,103,0,0,125,6,0,120,60,0,124,3,0,114, - 92,0,116,2,0,124,3,0,131,1,0,12,114,92,0,124, - 3,0,106,0,0,116,1,0,131,1,0,92,3,0,125,3, - 0,125,4,0,125,7,0,124,6,0,106,3,0,124,7,0, - 131,1,0,1,113,33,0,87,120,97,0,116,4,0,124,6, - 0,131,1,0,68,93,83,0,125,7,0,116,5,0,124,3, - 0,124,7,0,131,2,0,125,3,0,121,17,0,116,6,0, - 106,7,0,124,3,0,131,1,0,1,87,113,106,0,4,116, - 8,0,107,10,0,114,167,0,1,1,1,119,106,0,89,113, - 106,0,4,116,9,0,107,10,0,114,188,0,1,1,1,100, - 1,0,83,89,113,106,0,88,113,106,0,87,121,30,0,116, - 10,0,124,1,0,124,2,0,131,2,0,1,116,11,0,100, - 2,0,124,1,0,131,2,0,1,87,110,24,0,4,116,9, - 0,116,8,0,102,2,0,107,10,0,114,249,0,1,1,1, - 89,110,1,0,88,100,1,0,83,40,3,0,0,0,117,27, - 0,0,0,87,114,105,116,101,32,98,121,116,101,115,32,100, - 97,116,97,32,116,111,32,97,32,102,105,108,101,46,78,117, - 12,0,0,0,99,114,101,97,116,101,100,32,123,33,114,125, - 40,12,0,0,0,117,10,0,0,0,114,112,97,114,116,105, - 116,105,111,110,117,8,0,0,0,112,97,116,104,95,115,101, - 112,117,11,0,0,0,95,112,97,116,104,95,105,115,100,105, - 114,117,6,0,0,0,97,112,112,101,110,100,117,8,0,0, - 0,114,101,118,101,114,115,101,100,117,10,0,0,0,95,112, - 97,116,104,95,106,111,105,110,117,3,0,0,0,95,111,115, - 117,5,0,0,0,109,107,100,105,114,117,15,0,0,0,70, - 105,108,101,69,120,105,115,116,115,69,114,114,111,114,117,15, - 0,0,0,80,101,114,109,105,115,115,105,111,110,69,114,114, - 111,114,117,13,0,0,0,95,119,114,105,116,101,95,97,116, - 111,109,105,99,117,15,0,0,0,118,101,114,98,111,115,101, - 95,109,101,115,115,97,103,101,40,8,0,0,0,117,4,0, - 0,0,115,101,108,102,117,4,0,0,0,112,97,116,104,117, - 4,0,0,0,100,97,116,97,117,6,0,0,0,112,97,114, - 101,110,116,117,1,0,0,0,95,117,8,0,0,0,102,105, - 108,101,110,97,109,101,117,10,0,0,0,112,97,116,104,95, - 112,97,114,116,115,117,4,0,0,0,112,97,114,116,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,8,0,0,0,115, - 101,116,95,100,97,116,97,93,2,0,0,115,36,0,0,0, - 0,2,24,1,6,2,22,1,24,1,17,2,19,1,15,1, - 3,1,17,1,13,2,7,1,13,3,13,1,3,1,13,1, - 17,1,19,3,117,26,0,0,0,95,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,46,115,101,116,95,100, - 97,116,97,78,40,6,0,0,0,117,8,0,0,0,95,95, - 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, - 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, - 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, - 95,95,117,10,0,0,0,112,97,116,104,95,115,116,97,116, - 115,117,8,0,0,0,115,101,116,95,100,97,116,97,40,1, + 110,97,109,101,117,11,0,0,0,115,101,116,95,112,97,99, + 107,97,103,101,117,10,0,0,0,115,101,116,95,108,111,97, + 100,101,114,117,11,0,0,0,108,111,97,100,95,109,111,100, + 117,108,101,117,10,0,0,0,105,115,95,112,97,99,107,97, + 103,101,117,8,0,0,0,103,101,116,95,99,111,100,101,117, + 10,0,0,0,103,101,116,95,115,111,117,114,99,101,40,1, 0,0,0,117,10,0,0,0,95,95,108,111,99,97,108,115, 95,95,40,0,0,0,0,40,0,0,0,0,117,29,0,0, 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,17, - 0,0,0,95,83,111,117,114,99,101,70,105,108,101,76,111, - 97,100,101,114,84,2,0,0,115,6,0,0,0,16,2,6, - 2,12,5,117,17,0,0,0,95,83,111,117,114,99,101,70, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,20, + 0,0,0,95,69,120,116,101,110,115,105,111,110,70,105,108, + 101,76,111,97,100,101,114,146,2,0,0,115,16,0,0,0, + 16,6,6,2,12,4,3,1,3,1,24,13,18,5,18,5, + 117,20,0,0,0,95,69,120,116,101,110,115,105,111,110,70, 105,108,101,76,111,97,100,101,114,99,1,0,0,0,0,0, - 0,0,1,0,0,0,2,0,0,0,66,0,0,0,115,62, + 0,0,1,0,0,0,4,0,0,0,66,0,0,0,115,89, 0,0,0,124,0,0,69,101,0,0,90,1,0,100,0,0, - 90,2,0,100,1,0,90,3,0,100,2,0,100,3,0,132, - 0,0,90,4,0,100,4,0,100,5,0,132,0,0,90,5, - 0,100,6,0,100,7,0,132,0,0,90,6,0,100,8,0, - 83,40,9,0,0,0,117,21,0,0,0,95,83,111,117,114, - 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, - 117,45,0,0,0,76,111,97,100,101,114,32,119,104,105,99, - 104,32,104,97,110,100,108,101,115,32,115,111,117,114,99,101, - 108,101,115,115,32,102,105,108,101,32,105,109,112,111,114,116, - 115,46,99,2,0,0,0,0,0,0,0,2,0,0,0,4, - 0,0,0,67,0,0,0,115,19,0,0,0,124,0,0,106, - 0,0,124,1,0,100,1,0,100,2,0,131,1,1,83,40, - 3,0,0,0,78,117,10,0,0,0,115,111,117,114,99,101, - 108,101,115,115,84,40,2,0,0,0,117,12,0,0,0,95, - 108,111,97,100,95,109,111,100,117,108,101,117,4,0,0,0, - 84,114,117,101,40,2,0,0,0,117,4,0,0,0,115,101, - 108,102,117,8,0,0,0,102,117,108,108,110,97,109,101,40, - 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, - 108,111,97,100,95,109,111,100,117,108,101,126,2,0,0,115, - 2,0,0,0,0,1,117,33,0,0,0,95,83,111,117,114, - 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, - 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, - 0,0,0,0,0,6,0,0,0,6,0,0,0,67,0,0, - 0,115,138,0,0,0,124,0,0,106,0,0,124,1,0,131, - 1,0,125,2,0,124,0,0,106,1,0,124,2,0,131,1, - 0,125,3,0,124,0,0,106,2,0,124,1,0,124,3,0, - 124,2,0,100,0,0,131,4,0,125,4,0,116,4,0,106, - 5,0,124,4,0,131,1,0,125,5,0,116,6,0,124,5, - 0,116,7,0,131,2,0,114,101,0,116,8,0,100,1,0, - 124,2,0,131,2,0,1,124,5,0,83,116,9,0,100,2, - 0,106,10,0,124,2,0,131,1,0,100,3,0,124,1,0, - 100,4,0,124,2,0,131,1,2,130,1,0,100,0,0,83, - 40,5,0,0,0,78,117,21,0,0,0,99,111,100,101,32, - 111,98,106,101,99,116,32,102,114,111,109,32,123,33,114,125, - 117,21,0,0,0,78,111,110,45,99,111,100,101,32,111,98, - 106,101,99,116,32,105,110,32,123,125,117,4,0,0,0,110, - 97,109,101,117,4,0,0,0,112,97,116,104,40,11,0,0, - 0,117,12,0,0,0,103,101,116,95,102,105,108,101,110,97, - 109,101,117,8,0,0,0,103,101,116,95,100,97,116,97,117, - 20,0,0,0,95,98,121,116,101,115,95,102,114,111,109,95, - 98,121,116,101,99,111,100,101,117,4,0,0,0,78,111,110, - 101,117,7,0,0,0,109,97,114,115,104,97,108,117,5,0, - 0,0,108,111,97,100,115,117,10,0,0,0,105,115,105,110, - 115,116,97,110,99,101,117,9,0,0,0,99,111,100,101,95, - 116,121,112,101,117,15,0,0,0,118,101,114,98,111,115,101, - 95,109,101,115,115,97,103,101,117,11,0,0,0,73,109,112, - 111,114,116,69,114,114,111,114,117,6,0,0,0,102,111,114, - 109,97,116,40,6,0,0,0,117,4,0,0,0,115,101,108, - 102,117,8,0,0,0,102,117,108,108,110,97,109,101,117,4, - 0,0,0,112,97,116,104,117,4,0,0,0,100,97,116,97, - 117,10,0,0,0,98,121,116,101,115,95,100,97,116,97,117, - 5,0,0,0,102,111,117,110,100,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,8,0,0,0,103,101,116,95,99,111, - 100,101,129,2,0,0,115,18,0,0,0,0,1,15,1,15, - 1,24,1,15,1,15,1,13,1,4,2,18,1,117,30,0, - 0,0,95,83,111,117,114,99,101,108,101,115,115,70,105,108, - 101,76,111,97,100,101,114,46,103,101,116,95,99,111,100,101, - 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, - 0,67,0,0,0,115,4,0,0,0,100,1,0,83,40,2, - 0,0,0,117,39,0,0,0,82,101,116,117,114,110,32,78, - 111,110,101,32,97,115,32,116,104,101,114,101,32,105,115,32, - 110,111,32,115,111,117,114,99,101,32,99,111,100,101,46,78, - 40,1,0,0,0,117,4,0,0,0,78,111,110,101,40,2, - 0,0,0,117,4,0,0,0,115,101,108,102,117,8,0,0, - 0,102,117,108,108,110,97,109,101,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,10,0,0,0,103,101,116,95,115,111, - 117,114,99,101,141,2,0,0,115,2,0,0,0,0,2,117, - 32,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, - 105,108,101,76,111,97,100,101,114,46,103,101,116,95,115,111, - 117,114,99,101,78,40,7,0,0,0,117,8,0,0,0,95, - 95,110,97,109,101,95,95,117,10,0,0,0,95,95,109,111, - 100,117,108,101,95,95,117,12,0,0,0,95,95,113,117,97, - 108,110,97,109,101,95,95,117,7,0,0,0,95,95,100,111, - 99,95,95,117,11,0,0,0,108,111,97,100,95,109,111,100, - 117,108,101,117,8,0,0,0,103,101,116,95,99,111,100,101, - 117,10,0,0,0,103,101,116,95,115,111,117,114,99,101,40, + 90,2,0,100,1,0,90,3,0,101,4,0,100,8,0,100, + 2,0,100,3,0,132,1,0,131,1,0,90,6,0,101,4, + 0,100,8,0,100,4,0,100,5,0,132,1,0,131,1,0, + 90,7,0,101,4,0,100,8,0,100,6,0,100,7,0,132, + 1,0,131,1,0,90,8,0,100,8,0,83,40,9,0,0, + 0,117,10,0,0,0,80,97,116,104,70,105,110,100,101,114, + 117,63,0,0,0,77,101,116,97,32,112,97,116,104,32,102, + 105,110,100,101,114,32,102,111,114,32,115,121,115,46,40,112, + 97,116,104,124,112,97,116,104,95,104,111,111,107,115,124,112, + 97,116,104,95,105,109,112,111,114,116,101,114,95,99,97,99, + 104,101,41,46,99,3,0,0,0,0,0,0,0,4,0,0, + 0,12,0,0,0,67,0,0,0,115,104,0,0,0,124,2, + 0,115,18,0,116,0,0,106,1,0,125,2,0,110,0,0, + 120,79,0,124,2,0,68,93,44,0,125,3,0,121,14,0, + 124,3,0,124,1,0,131,1,0,83,87,113,25,0,4,116, + 2,0,107,10,0,114,68,0,1,1,1,119,25,0,89,113, + 25,0,88,113,25,0,87,116,2,0,100,1,0,106,3,0, + 124,1,0,131,1,0,100,2,0,124,1,0,131,1,1,130, + 1,0,100,3,0,83,40,4,0,0,0,117,113,0,0,0, + 83,101,97,114,99,104,32,115,101,113,117,101,110,99,101,32, + 111,102,32,104,111,111,107,115,32,102,111,114,32,97,32,102, + 105,110,100,101,114,32,102,111,114,32,39,112,97,116,104,39, + 46,10,10,32,32,32,32,32,32,32,32,73,102,32,39,104, + 111,111,107,115,39,32,105,115,32,102,97,108,115,101,32,116, + 104,101,110,32,117,115,101,32,115,121,115,46,112,97,116,104, + 95,104,111,111,107,115,46,10,10,32,32,32,32,32,32,32, + 32,117,26,0,0,0,110,111,32,112,97,116,104,32,104,111, + 111,107,32,102,111,117,110,100,32,102,111,114,32,123,48,125, + 117,4,0,0,0,112,97,116,104,78,40,4,0,0,0,117, + 3,0,0,0,115,121,115,117,10,0,0,0,112,97,116,104, + 95,104,111,111,107,115,117,11,0,0,0,73,109,112,111,114, + 116,69,114,114,111,114,117,6,0,0,0,102,111,114,109,97, + 116,40,4,0,0,0,117,3,0,0,0,99,108,115,117,4, + 0,0,0,112,97,116,104,117,5,0,0,0,104,111,111,107, + 115,117,4,0,0,0,104,111,111,107,40,0,0,0,0,40, + 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, + 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, + 115,116,114,97,112,62,117,11,0,0,0,95,112,97,116,104, + 95,104,111,111,107,115,195,2,0,0,115,18,0,0,0,0, + 7,6,1,12,1,13,1,3,1,14,1,13,1,12,2,18, + 1,117,22,0,0,0,80,97,116,104,70,105,110,100,101,114, + 46,95,112,97,116,104,95,104,111,111,107,115,99,3,0,0, + 0,0,0,0,0,4,0,0,0,12,0,0,0,67,0,0, + 0,115,137,0,0,0,124,1,0,100,1,0,107,2,0,114, + 21,0,100,2,0,125,1,0,110,0,0,121,17,0,116,0, + 0,106,1,0,124,1,0,25,125,3,0,87,110,46,0,4, + 116,2,0,107,10,0,114,86,0,1,1,1,124,0,0,106, + 3,0,124,1,0,131,1,0,125,3,0,124,3,0,116,0, + 0,106,1,0,124,1,0,60,89,110,47,0,88,124,3,0, + 100,3,0,107,8,0,114,133,0,124,2,0,114,133,0,124, + 2,0,124,1,0,131,1,0,125,3,0,124,3,0,116,0, + 0,106,1,0,124,1,0,60,110,0,0,124,3,0,83,40, + 4,0,0,0,117,199,1,0,0,71,101,116,32,116,104,101, + 32,102,105,110,100,101,114,32,102,111,114,32,116,104,101,32, + 112,97,116,104,32,102,114,111,109,32,115,121,115,46,112,97, + 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, + 101,46,10,10,32,32,32,32,32,32,32,32,73,102,32,116, + 104,101,32,112,97,116,104,32,105,115,32,110,111,116,32,105, + 110,32,116,104,101,32,99,97,99,104,101,44,32,102,105,110, + 100,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116, + 101,32,102,105,110,100,101,114,32,97,110,100,32,99,97,99, + 104,101,10,32,32,32,32,32,32,32,32,105,116,46,32,73, + 102,32,78,111,110,101,32,105,115,32,99,97,99,104,101,100, + 44,32,103,101,116,32,116,104,101,32,100,101,102,97,117,108, + 116,32,102,105,110,100,101,114,32,97,110,100,32,99,97,99, + 104,101,32,116,104,97,116,10,32,32,32,32,32,32,32,32, + 40,105,102,32,97,112,112,108,105,99,97,98,108,101,41,46, + 10,10,32,32,32,32,32,32,32,32,66,101,99,97,117,115, + 101,32,111,102,32,78,117,108,108,73,109,112,111,114,116,101, + 114,44,32,115,111,109,101,32,102,105,110,100,101,114,32,115, + 104,111,117,108,100,32,98,101,32,114,101,116,117,114,110,101, + 100,46,32,84,104,101,32,111,110,108,121,10,32,32,32,32, + 32,32,32,32,101,120,112,108,105,99,105,116,32,102,97,105, + 108,32,99,97,115,101,32,105,115,32,105,102,32,78,111,110, + 101,32,105,115,32,99,97,99,104,101,100,32,98,117,116,32, + 116,104,101,32,112,97,116,104,32,99,97,110,110,111,116,32, + 98,101,32,117,115,101,100,32,102,111,114,10,32,32,32,32, + 32,32,32,32,116,104,101,32,100,101,102,97,117,108,116,32, + 104,111,111,107,44,32,102,111,114,32,119,104,105,99,104,32, + 73,109,112,111,114,116,69,114,114,111,114,32,105,115,32,114, + 97,105,115,101,100,46,10,10,32,32,32,32,32,32,32,32, + 117,0,0,0,0,117,1,0,0,0,46,78,40,5,0,0, + 0,117,3,0,0,0,115,121,115,117,19,0,0,0,112,97, + 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, + 101,117,8,0,0,0,75,101,121,69,114,114,111,114,117,11, + 0,0,0,95,112,97,116,104,95,104,111,111,107,115,117,4, + 0,0,0,78,111,110,101,40,4,0,0,0,117,3,0,0, + 0,99,108,115,117,4,0,0,0,112,97,116,104,117,7,0, + 0,0,100,101,102,97,117,108,116,117,6,0,0,0,102,105, + 110,100,101,114,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,20,0,0,0,95,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,213,2,0,0,115,22,0, + 0,0,0,13,12,1,9,1,3,1,17,1,13,1,15,1, + 18,2,18,2,12,1,16,1,117,31,0,0,0,80,97,116, + 104,70,105,110,100,101,114,46,95,112,97,116,104,95,105,109, + 112,111,114,116,101,114,95,99,97,99,104,101,99,3,0,0, + 0,0,0,0,0,6,0,0,0,12,0,0,0,67,0,0, + 0,115,120,0,0,0,124,2,0,115,18,0,116,0,0,106, + 1,0,125,2,0,110,0,0,120,95,0,124,2,0,68,93, + 83,0,125,3,0,121,19,0,124,0,0,106,2,0,124,3, + 0,131,1,0,125,4,0,87,110,21,0,4,116,3,0,107, + 10,0,114,73,0,1,1,1,119,25,0,89,110,1,0,88, + 124,4,0,114,25,0,124,4,0,106,4,0,124,1,0,131, + 1,0,125,5,0,124,5,0,114,108,0,124,5,0,83,113, + 25,0,113,25,0,87,100,1,0,83,100,1,0,83,40,2, + 0,0,0,117,98,0,0,0,70,105,110,100,32,116,104,101, + 32,109,111,100,117,108,101,32,111,110,32,115,121,115,46,112, + 97,116,104,32,111,114,32,39,112,97,116,104,39,32,98,97, + 115,101,100,32,111,110,32,115,121,115,46,112,97,116,104,95, + 104,111,111,107,115,32,97,110,100,10,32,32,32,32,32,32, + 32,32,115,121,115,46,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,46,78,40,6,0,0,0, + 117,3,0,0,0,115,121,115,117,4,0,0,0,112,97,116, + 104,117,20,0,0,0,95,112,97,116,104,95,105,109,112,111, + 114,116,101,114,95,99,97,99,104,101,117,11,0,0,0,73, + 109,112,111,114,116,69,114,114,111,114,117,11,0,0,0,102, + 105,110,100,95,109,111,100,117,108,101,117,4,0,0,0,78, + 111,110,101,40,6,0,0,0,117,3,0,0,0,99,108,115, + 117,8,0,0,0,102,117,108,108,110,97,109,101,117,4,0, + 0,0,112,97,116,104,117,5,0,0,0,101,110,116,114,121, + 117,6,0,0,0,102,105,110,100,101,114,117,6,0,0,0, + 108,111,97,100,101,114,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,11,0,0,0,102,105,110,100,95,109,111,100,117, + 108,101,240,2,0,0,115,24,0,0,0,0,4,6,1,12, + 1,13,1,3,1,19,1,13,1,8,1,6,1,15,1,6, + 1,11,2,117,22,0,0,0,80,97,116,104,70,105,110,100, + 101,114,46,102,105,110,100,95,109,111,100,117,108,101,78,40, + 9,0,0,0,117,8,0,0,0,95,95,110,97,109,101,95, + 95,117,10,0,0,0,95,95,109,111,100,117,108,101,95,95, + 117,12,0,0,0,95,95,113,117,97,108,110,97,109,101,95, + 95,117,7,0,0,0,95,95,100,111,99,95,95,117,11,0, + 0,0,99,108,97,115,115,109,101,116,104,111,100,117,4,0, + 0,0,78,111,110,101,117,11,0,0,0,95,112,97,116,104, + 95,104,111,111,107,115,117,20,0,0,0,95,112,97,116,104, + 95,105,109,112,111,114,116,101,114,95,99,97,99,104,101,117, + 11,0,0,0,102,105,110,100,95,109,111,100,117,108,101,40, 1,0,0,0,117,10,0,0,0,95,95,108,111,99,97,108, 115,95,95,40,0,0,0,0,40,0,0,0,0,117,29,0, 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, - 105,108,101,76,111,97,100,101,114,122,2,0,0,115,8,0, - 0,0,16,2,6,2,12,3,12,12,117,21,0,0,0,95, - 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, - 97,100,101,114,99,1,0,0,0,0,0,0,0,1,0,0, - 0,5,0,0,0,66,0,0,0,115,122,0,0,0,124,0, + 10,0,0,0,80,97,116,104,70,105,110,100,101,114,191,2, + 0,0,115,14,0,0,0,16,2,6,2,3,1,18,17,3, + 1,18,26,3,1,117,10,0,0,0,80,97,116,104,70,105, + 110,100,101,114,99,1,0,0,0,0,0,0,0,1,0,0, + 0,2,0,0,0,66,0,0,0,115,74,0,0,0,124,0, 0,69,101,0,0,90,1,0,100,0,0,90,2,0,100,1, 0,90,3,0,100,2,0,100,3,0,132,0,0,90,4,0, - 101,5,0,101,6,0,101,7,0,100,4,0,100,5,0,132, - 0,0,131,1,0,131,1,0,131,1,0,90,8,0,101,5, - 0,100,6,0,100,7,0,132,0,0,131,1,0,90,9,0, - 101,5,0,100,8,0,100,9,0,132,0,0,131,1,0,90, - 10,0,101,5,0,100,10,0,100,11,0,132,0,0,131,1, - 0,90,11,0,100,12,0,83,40,13,0,0,0,117,20,0, - 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,117,93,0,0,0,76,111,97,100,101, - 114,32,102,111,114,32,101,120,116,101,110,115,105,111,110,32, - 109,111,100,117,108,101,115,46,10,10,32,32,32,32,84,104, - 101,32,99,111,110,115,116,114,117,99,116,111,114,32,105,115, - 32,100,101,115,105,103,110,101,100,32,116,111,32,119,111,114, - 107,32,119,105,116,104,32,70,105,108,101,70,105,110,100,101, - 114,46,10,10,32,32,32,32,99,3,0,0,0,0,0,0, - 0,3,0,0,0,2,0,0,0,67,0,0,0,115,22,0, - 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, - 0,95,1,0,100,0,0,83,40,1,0,0,0,78,40,2, - 0,0,0,117,5,0,0,0,95,110,97,109,101,117,5,0, - 0,0,95,112,97,116,104,40,3,0,0,0,117,4,0,0, - 0,115,101,108,102,117,4,0,0,0,110,97,109,101,117,4, - 0,0,0,112,97,116,104,40,0,0,0,0,40,0,0,0, - 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, - 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,8,0,0,0,95,95,105,110,105,116,95,95, - 154,2,0,0,115,4,0,0,0,0,1,9,1,117,29,0, - 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,46,95,95,105,110,105,116,95,95,99, - 2,0,0,0,0,0,0,0,4,0,0,0,9,0,0,0, - 67,0,0,0,115,113,0,0,0,124,1,0,116,0,0,106, - 1,0,107,6,0,125,2,0,121,45,0,116,2,0,106,3, - 0,124,1,0,124,0,0,106,4,0,131,2,0,125,3,0, - 116,5,0,100,1,0,124,0,0,106,4,0,131,2,0,1, - 124,3,0,83,87,110,46,0,1,1,1,124,2,0,12,114, - 101,0,124,1,0,116,0,0,106,1,0,107,6,0,114,101, - 0,116,0,0,106,1,0,124,1,0,61,110,0,0,130,0, - 0,89,110,1,0,88,100,2,0,83,40,3,0,0,0,117, - 25,0,0,0,76,111,97,100,32,97,110,32,101,120,116,101, - 110,115,105,111,110,32,109,111,100,117,108,101,46,117,33,0, - 0,0,101,120,116,101,110,115,105,111,110,32,109,111,100,117, - 108,101,32,108,111,97,100,101,100,32,102,114,111,109,32,123, - 33,114,125,78,40,6,0,0,0,117,3,0,0,0,115,121, - 115,117,7,0,0,0,109,111,100,117,108,101,115,117,4,0, - 0,0,95,105,109,112,117,12,0,0,0,108,111,97,100,95, - 100,121,110,97,109,105,99,117,5,0,0,0,95,112,97,116, - 104,117,15,0,0,0,118,101,114,98,111,115,101,95,109,101, - 115,115,97,103,101,40,4,0,0,0,117,4,0,0,0,115, - 101,108,102,117,8,0,0,0,102,117,108,108,110,97,109,101, - 117,9,0,0,0,105,115,95,114,101,108,111,97,100,117,6, - 0,0,0,109,111,100,117,108,101,40,0,0,0,0,40,0, + 100,4,0,100,5,0,132,0,0,90,5,0,100,6,0,100, + 7,0,132,0,0,90,6,0,100,8,0,100,9,0,132,0, + 0,90,7,0,100,10,0,83,40,11,0,0,0,117,11,0, + 0,0,95,70,105,108,101,70,105,110,100,101,114,117,171,0, + 0,0,70,105,108,101,45,98,97,115,101,100,32,102,105,110, + 100,101,114,46,10,10,32,32,32,32,67,111,110,115,116,114, + 117,99,116,111,114,32,116,97,107,101,115,32,97,32,108,105, + 115,116,32,111,102,32,111,98,106,101,99,116,115,32,100,101, + 116,97,105,108,105,110,103,32,119,104,97,116,32,102,105,108, + 101,32,101,120,116,101,110,115,105,111,110,115,32,116,104,101, + 105,114,10,32,32,32,32,108,111,97,100,101,114,32,115,117, + 112,112,111,114,116,115,32,97,108,111,110,103,32,119,105,116, + 104,32,119,104,101,116,104,101,114,32,105,116,32,99,97,110, + 32,98,101,32,117,115,101,100,32,102,111,114,32,97,32,112, + 97,99,107,97,103,101,46,10,10,32,32,32,32,99,2,0, + 0,0,0,0,0,0,5,0,0,0,5,0,0,0,7,0, + 0,0,115,181,0,0,0,103,0,0,125,3,0,103,0,0, + 125,4,0,120,96,0,124,2,0,68,93,88,0,137,0,0, + 124,4,0,106,0,0,135,0,0,102,1,0,100,1,0,100, + 2,0,134,0,0,136,0,0,106,1,0,68,131,1,0,131, + 1,0,1,136,0,0,106,2,0,114,19,0,124,3,0,106, + 0,0,135,0,0,102,1,0,100,3,0,100,2,0,134,0, + 0,136,0,0,106,1,0,68,131,1,0,131,1,0,1,113, + 19,0,113,19,0,87,124,3,0,124,0,0,95,3,0,124, + 4,0,124,0,0,95,4,0,124,1,0,112,138,0,100,4, + 0,124,0,0,95,5,0,100,7,0,124,0,0,95,6,0, + 116,7,0,131,0,0,124,0,0,95,8,0,116,7,0,131, + 0,0,124,0,0,95,9,0,100,6,0,83,40,8,0,0, + 0,117,31,0,0,0,73,110,105,116,105,97,108,105,122,101, + 32,119,105,116,104,32,102,105,110,100,101,114,32,100,101,116, + 97,105,108,115,46,99,1,0,0,0,0,0,0,0,2,0, + 0,0,3,0,0,0,51,0,0,0,115,30,0,0,0,124, + 0,0,93,20,0,125,1,0,124,1,0,136,0,0,106,0, + 0,102,2,0,86,1,113,3,0,100,0,0,83,40,1,0, + 0,0,78,40,1,0,0,0,117,6,0,0,0,108,111,97, + 100,101,114,40,2,0,0,0,117,2,0,0,0,46,48,117, + 6,0,0,0,115,117,102,102,105,120,40,1,0,0,0,117, + 6,0,0,0,100,101,116,97,105,108,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,9,0,0,0,60,103,101,110,101,120,112,114,62,17, + 3,0,0,115,2,0,0,0,6,0,117,39,0,0,0,95, + 70,105,108,101,70,105,110,100,101,114,46,95,95,105,110,105, + 116,95,95,46,60,108,111,99,97,108,115,62,46,60,103,101, + 110,101,120,112,114,62,99,1,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,51,0,0,0,115,30,0,0,0, + 124,0,0,93,20,0,125,1,0,124,1,0,136,0,0,106, + 0,0,102,2,0,86,1,113,3,0,100,0,0,83,40,1, + 0,0,0,78,40,1,0,0,0,117,6,0,0,0,108,111, + 97,100,101,114,40,2,0,0,0,117,2,0,0,0,46,48, + 117,6,0,0,0,115,117,102,102,105,120,40,1,0,0,0, + 117,6,0,0,0,100,101,116,97,105,108,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,9,0,0,0,60,103,101,110,101,120,112,114,62, + 19,3,0,0,115,2,0,0,0,6,1,117,1,0,0,0, + 46,105,1,0,0,0,78,105,255,255,255,255,40,10,0,0, + 0,117,6,0,0,0,101,120,116,101,110,100,117,8,0,0, + 0,115,117,102,102,105,120,101,115,117,17,0,0,0,115,117, + 112,112,111,114,116,115,95,112,97,99,107,97,103,101,115,117, + 8,0,0,0,112,97,99,107,97,103,101,115,117,7,0,0, + 0,109,111,100,117,108,101,115,117,4,0,0,0,112,97,116, + 104,117,11,0,0,0,95,112,97,116,104,95,109,116,105,109, + 101,117,3,0,0,0,115,101,116,117,11,0,0,0,95,112, + 97,116,104,95,99,97,99,104,101,117,19,0,0,0,95,114, + 101,108,97,120,101,100,95,112,97,116,104,95,99,97,99,104, + 101,40,5,0,0,0,117,4,0,0,0,115,101,108,102,117, + 4,0,0,0,112,97,116,104,117,7,0,0,0,100,101,116, + 97,105,108,115,117,8,0,0,0,112,97,99,107,97,103,101, + 115,117,7,0,0,0,109,111,100,117,108,101,115,40,0,0, + 0,0,40,1,0,0,0,117,6,0,0,0,100,101,116,97, + 105,108,117,29,0,0,0,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,117,8,0,0,0,95,95,105,110,105,116,95, + 95,12,3,0,0,115,26,0,0,0,0,2,6,1,6,1, + 13,1,35,1,9,1,21,1,21,1,9,1,9,2,15,1, + 9,1,12,1,117,20,0,0,0,95,70,105,108,101,70,105, + 110,100,101,114,46,95,95,105,110,105,116,95,95,99,1,0, + 0,0,0,0,0,0,1,0,0,0,2,0,0,0,67,0, + 0,0,115,13,0,0,0,100,3,0,124,0,0,95,0,0, + 100,2,0,83,40,4,0,0,0,117,31,0,0,0,73,110, + 118,97,108,105,100,97,116,101,32,116,104,101,32,100,105,114, + 101,99,116,111,114,121,32,109,116,105,109,101,46,105,1,0, + 0,0,78,105,255,255,255,255,40,1,0,0,0,117,11,0, + 0,0,95,112,97,116,104,95,109,116,105,109,101,40,1,0, + 0,0,117,4,0,0,0,115,101,108,102,40,0,0,0,0, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,17,0,0,0,105,110,118,97, + 108,105,100,97,116,101,95,99,97,99,104,101,115,29,3,0, + 0,115,2,0,0,0,0,2,117,29,0,0,0,95,70,105, + 108,101,70,105,110,100,101,114,46,105,110,118,97,108,105,100, + 97,116,101,95,99,97,99,104,101,115,99,2,0,0,0,0, + 0,0,0,12,0,0,0,13,0,0,0,67,0,0,0,115, + 151,1,0,0,124,1,0,106,0,0,100,1,0,131,1,0, + 100,2,0,25,125,2,0,121,25,0,116,1,0,106,2,0, + 124,0,0,106,3,0,131,1,0,106,4,0,125,3,0,87, + 110,24,0,4,116,5,0,107,10,0,114,70,0,1,1,1, + 100,6,0,125,3,0,89,110,1,0,88,124,3,0,124,0, + 0,106,6,0,107,3,0,114,108,0,124,0,0,106,7,0, + 131,0,0,1,124,3,0,124,0,0,95,6,0,110,0,0, + 116,8,0,131,0,0,114,141,0,124,0,0,106,9,0,125, + 4,0,124,2,0,106,10,0,131,0,0,125,5,0,110,15, + 0,124,0,0,106,11,0,125,4,0,124,2,0,125,5,0, + 124,5,0,124,4,0,107,6,0,114,55,1,116,12,0,124, + 0,0,106,3,0,124,2,0,131,2,0,125,6,0,116,13, + 0,124,6,0,131,1,0,114,55,1,120,107,0,124,0,0, + 106,14,0,68,93,62,0,92,2,0,125,7,0,125,8,0, + 100,4,0,124,7,0,23,125,9,0,116,12,0,124,6,0, + 124,9,0,131,2,0,125,10,0,116,15,0,124,10,0,131, + 1,0,114,208,0,124,8,0,124,1,0,124,10,0,131,2, + 0,83,113,208,0,87,100,5,0,125,11,0,116,16,0,106, + 17,0,124,11,0,106,18,0,124,6,0,131,1,0,116,19, + 0,131,2,0,1,113,55,1,110,0,0,120,89,0,124,0, + 0,106,20,0,68,93,78,0,92,2,0,125,7,0,125,8, + 0,124,5,0,124,7,0,23,124,4,0,107,6,0,114,65, + 1,116,12,0,124,0,0,106,3,0,124,2,0,124,7,0, + 23,131,2,0,125,10,0,116,15,0,124,10,0,131,1,0, + 114,143,1,124,8,0,124,1,0,124,10,0,131,2,0,83, + 113,65,1,113,65,1,87,100,7,0,83,40,8,0,0,0, + 117,46,0,0,0,84,114,121,32,116,111,32,102,105,110,100, + 32,97,32,108,111,97,100,101,114,32,102,111,114,32,116,104, + 101,32,115,112,101,99,105,102,105,101,100,32,109,111,100,117, + 108,101,46,117,1,0,0,0,46,105,2,0,0,0,105,1, + 0,0,0,117,8,0,0,0,95,95,105,110,105,116,95,95, + 117,44,0,0,0,78,111,116,32,105,109,112,111,114,116,105, + 110,103,32,100,105,114,101,99,116,111,114,121,32,123,125,58, + 32,109,105,115,115,105,110,103,32,95,95,105,110,105,116,95, + 95,105,255,255,255,255,78,40,22,0,0,0,117,10,0,0, + 0,114,112,97,114,116,105,116,105,111,110,117,3,0,0,0, + 95,111,115,117,4,0,0,0,115,116,97,116,117,4,0,0, + 0,112,97,116,104,117,8,0,0,0,115,116,95,109,116,105, + 109,101,117,7,0,0,0,79,83,69,114,114,111,114,117,11, + 0,0,0,95,112,97,116,104,95,109,116,105,109,101,117,11, + 0,0,0,95,102,105,108,108,95,99,97,99,104,101,117,11, + 0,0,0,95,114,101,108,97,120,95,99,97,115,101,117,19, + 0,0,0,95,114,101,108,97,120,101,100,95,112,97,116,104, + 95,99,97,99,104,101,117,5,0,0,0,108,111,119,101,114, + 117,11,0,0,0,95,112,97,116,104,95,99,97,99,104,101, + 117,10,0,0,0,95,112,97,116,104,95,106,111,105,110,117, + 11,0,0,0,95,112,97,116,104,95,105,115,100,105,114,117, + 8,0,0,0,112,97,99,107,97,103,101,115,117,12,0,0, + 0,95,112,97,116,104,95,105,115,102,105,108,101,117,9,0, + 0,0,95,119,97,114,110,105,110,103,115,117,4,0,0,0, + 119,97,114,110,117,6,0,0,0,102,111,114,109,97,116,117, + 13,0,0,0,73,109,112,111,114,116,87,97,114,110,105,110, + 103,117,7,0,0,0,109,111,100,117,108,101,115,117,4,0, + 0,0,78,111,110,101,40,12,0,0,0,117,4,0,0,0, + 115,101,108,102,117,8,0,0,0,102,117,108,108,110,97,109, + 101,117,11,0,0,0,116,97,105,108,95,109,111,100,117,108, + 101,117,5,0,0,0,109,116,105,109,101,117,5,0,0,0, + 99,97,99,104,101,117,12,0,0,0,99,97,99,104,101,95, + 109,111,100,117,108,101,117,9,0,0,0,98,97,115,101,95, + 112,97,116,104,117,6,0,0,0,115,117,102,102,105,120,117, + 6,0,0,0,108,111,97,100,101,114,117,13,0,0,0,105, + 110,105,116,95,102,105,108,101,110,97,109,101,117,9,0,0, + 0,102,117,108,108,95,112,97,116,104,117,3,0,0,0,109, + 115,103,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,11, + 0,0,0,102,105,110,100,95,109,111,100,117,108,101,33,3, + 0,0,115,58,0,0,0,0,2,19,1,3,1,25,1,13, + 1,11,1,15,1,10,1,12,2,9,1,9,1,15,2,9, + 1,6,2,12,1,18,1,12,1,22,1,10,1,15,1,12, + 1,17,2,6,1,31,2,22,1,16,1,22,1,12,1,20, + 1,117,23,0,0,0,95,70,105,108,101,70,105,110,100,101, + 114,46,102,105,110,100,95,109,111,100,117,108,101,99,1,0, + 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, + 0,0,115,71,0,0,0,124,0,0,106,0,0,125,1,0, + 116,1,0,106,2,0,124,1,0,131,1,0,125,2,0,116, + 3,0,124,2,0,131,1,0,124,0,0,95,4,0,116,3, + 0,100,1,0,100,2,0,132,0,0,124,2,0,68,131,1, + 0,131,1,0,124,0,0,95,5,0,100,3,0,83,40,4, + 0,0,0,117,68,0,0,0,70,105,108,108,32,116,104,101, + 32,99,97,99,104,101,32,111,102,32,112,111,116,101,110,116, + 105,97,108,32,109,111,100,117,108,101,115,32,97,110,100,32, + 112,97,99,107,97,103,101,115,32,102,111,114,32,116,104,105, + 115,32,100,105,114,101,99,116,111,114,121,46,99,1,0,0, + 0,0,0,0,0,2,0,0,0,2,0,0,0,115,0,0, + 0,115,27,0,0,0,124,0,0,93,17,0,125,1,0,124, + 1,0,106,0,0,131,0,0,86,1,113,3,0,100,0,0, + 83,40,1,0,0,0,78,40,1,0,0,0,117,5,0,0, + 0,108,111,119,101,114,40,2,0,0,0,117,2,0,0,0, + 46,48,117,2,0,0,0,102,110,40,0,0,0,0,40,0, 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,11,0,0,0,108,111,97,100,95,109, - 111,100,117,108,101,158,2,0,0,115,18,0,0,0,0,5, - 15,1,3,1,21,1,16,1,8,1,3,1,22,1,13,1, - 117,32,0,0,0,95,69,120,116,101,110,115,105,111,110,70, - 105,108,101,76,111,97,100,101,114,46,108,111,97,100,95,109, - 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, - 1,0,83,40,2,0,0,0,117,59,0,0,0,82,101,116, - 117,114,110,32,70,97,108,115,101,32,97,115,32,97,110,32, - 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, - 32,99,97,110,32,110,101,118,101,114,32,98,101,32,97,32, - 112,97,99,107,97,103,101,46,70,40,1,0,0,0,117,5, - 0,0,0,70,97,108,115,101,40,2,0,0,0,117,4,0, - 0,0,115,101,108,102,117,8,0,0,0,102,117,108,108,110, - 97,109,101,40,0,0,0,0,40,0,0,0,0,117,29,0, + 116,114,97,112,62,117,9,0,0,0,60,103,101,110,101,120, + 112,114,62,77,3,0,0,115,2,0,0,0,6,0,117,42, + 0,0,0,95,70,105,108,101,70,105,110,100,101,114,46,95, + 102,105,108,108,95,99,97,99,104,101,46,60,108,111,99,97, + 108,115,62,46,60,103,101,110,101,120,112,114,62,78,40,6, + 0,0,0,117,4,0,0,0,112,97,116,104,117,3,0,0, + 0,95,111,115,117,7,0,0,0,108,105,115,116,100,105,114, + 117,3,0,0,0,115,101,116,117,11,0,0,0,95,112,97, + 116,104,95,99,97,99,104,101,117,19,0,0,0,95,114,101, + 108,97,120,101,100,95,112,97,116,104,95,99,97,99,104,101, + 40,3,0,0,0,117,4,0,0,0,115,101,108,102,117,4, + 0,0,0,112,97,116,104,117,8,0,0,0,99,111,110,116, + 101,110,116,115,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,11,0,0,0,95,102,105,108,108,95,99,97,99,104,101, + 70,3,0,0,115,8,0,0,0,0,2,9,1,15,3,15, + 1,117,23,0,0,0,95,70,105,108,101,70,105,110,100,101, + 114,46,95,102,105,108,108,95,99,97,99,104,101,78,40,8, + 0,0,0,117,8,0,0,0,95,95,110,97,109,101,95,95, + 117,10,0,0,0,95,95,109,111,100,117,108,101,95,95,117, + 12,0,0,0,95,95,113,117,97,108,110,97,109,101,95,95, + 117,7,0,0,0,95,95,100,111,99,95,95,117,8,0,0, + 0,95,95,105,110,105,116,95,95,117,17,0,0,0,105,110, + 118,97,108,105,100,97,116,101,95,99,97,99,104,101,115,117, + 11,0,0,0,102,105,110,100,95,109,111,100,117,108,101,117, + 11,0,0,0,95,102,105,108,108,95,99,97,99,104,101,40, + 1,0,0,0,117,10,0,0,0,95,95,108,111,99,97,108, + 115,95,95,40,0,0,0,0,40,0,0,0,0,117,29,0, 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 10,0,0,0,105,115,95,112,97,99,107,97,103,101,173,2, - 0,0,115,2,0,0,0,0,3,117,31,0,0,0,95,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,46,105,115,95,112,97,99,107,97,103,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,1,0,83,40,2,0,0,0, - 117,63,0,0,0,82,101,116,117,114,110,32,78,111,110,101, - 32,97,115,32,97,110,32,101,120,116,101,110,115,105,111,110, - 32,109,111,100,117,108,101,32,99,97,110,110,111,116,32,99, - 114,101,97,116,101,32,97,32,99,111,100,101,32,111,98,106, - 101,99,116,46,78,40,1,0,0,0,117,4,0,0,0,78, - 111,110,101,40,2,0,0,0,117,4,0,0,0,115,101,108, - 102,117,8,0,0,0,102,117,108,108,110,97,109,101,40,0, - 0,0,0,40,0,0,0,0,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,8,0,0,0,103, - 101,116,95,99,111,100,101,178,2,0,0,115,2,0,0,0, - 0,3,117,29,0,0,0,95,69,120,116,101,110,115,105,111, - 110,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95, - 99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, - 0,83,40,2,0,0,0,117,53,0,0,0,82,101,116,117, - 114,110,32,78,111,110,101,32,97,115,32,101,120,116,101,110, - 115,105,111,110,32,109,111,100,117,108,101,115,32,104,97,118, - 101,32,110,111,32,115,111,117,114,99,101,32,99,111,100,101, - 46,78,40,1,0,0,0,117,4,0,0,0,78,111,110,101, - 40,2,0,0,0,117,4,0,0,0,115,101,108,102,117,8, - 0,0,0,102,117,108,108,110,97,109,101,40,0,0,0,0, - 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, - 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, - 116,115,116,114,97,112,62,117,10,0,0,0,103,101,116,95, - 115,111,117,114,99,101,183,2,0,0,115,2,0,0,0,0, - 3,117,31,0,0,0,95,69,120,116,101,110,115,105,111,110, - 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,115, - 111,117,114,99,101,78,40,12,0,0,0,117,8,0,0,0, - 95,95,110,97,109,101,95,95,117,10,0,0,0,95,95,109, - 111,100,117,108,101,95,95,117,12,0,0,0,95,95,113,117, - 97,108,110,97,109,101,95,95,117,7,0,0,0,95,95,100, - 111,99,95,95,117,8,0,0,0,95,95,105,110,105,116,95, - 95,117,11,0,0,0,95,99,104,101,99,107,95,110,97,109, - 101,117,11,0,0,0,115,101,116,95,112,97,99,107,97,103, - 101,117,10,0,0,0,115,101,116,95,108,111,97,100,101,114, - 117,11,0,0,0,108,111,97,100,95,109,111,100,117,108,101, - 117,10,0,0,0,105,115,95,112,97,99,107,97,103,101,117, - 8,0,0,0,103,101,116,95,99,111,100,101,117,10,0,0, - 0,103,101,116,95,115,111,117,114,99,101,40,1,0,0,0, + 11,0,0,0,95,70,105,108,101,70,105,110,100,101,114,3, + 3,0,0,115,10,0,0,0,16,7,6,2,12,17,12,4, + 12,37,117,11,0,0,0,95,70,105,108,101,70,105,110,100, + 101,114,99,1,0,0,0,0,0,0,0,1,0,0,0,2, + 0,0,0,66,0,0,0,115,44,0,0,0,124,0,0,69, + 101,0,0,90,1,0,100,0,0,90,2,0,101,3,0,90, + 4,0,100,4,0,90,6,0,100,1,0,100,2,0,132,0, + 0,90,7,0,100,3,0,83,40,5,0,0,0,117,20,0, + 0,0,95,83,111,117,114,99,101,70,105,110,100,101,114,68, + 101,116,97,105,108,115,99,1,0,0,0,0,0,0,0,1, + 0,0,0,2,0,0,0,67,0,0,0,115,22,0,0,0, + 116,0,0,116,1,0,106,2,0,131,1,0,124,0,0,95, + 3,0,100,0,0,83,40,1,0,0,0,78,40,4,0,0, + 0,117,12,0,0,0,95,115,117,102,102,105,120,95,108,105, + 115,116,117,4,0,0,0,95,105,109,112,117,9,0,0,0, + 80,89,95,83,79,85,82,67,69,117,8,0,0,0,115,117, + 102,102,105,120,101,115,40,1,0,0,0,117,4,0,0,0, + 115,101,108,102,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,8,0,0,0,95,95,105,110,105,116,95,95,85,3,0, + 0,115,2,0,0,0,0,1,117,29,0,0,0,95,83,111, + 117,114,99,101,70,105,110,100,101,114,68,101,116,97,105,108, + 115,46,95,95,105,110,105,116,95,95,78,84,40,8,0,0, + 0,117,8,0,0,0,95,95,110,97,109,101,95,95,117,10, + 0,0,0,95,95,109,111,100,117,108,101,95,95,117,12,0, + 0,0,95,95,113,117,97,108,110,97,109,101,95,95,117,17, + 0,0,0,95,83,111,117,114,99,101,70,105,108,101,76,111, + 97,100,101,114,117,6,0,0,0,108,111,97,100,101,114,117, + 4,0,0,0,84,114,117,101,117,17,0,0,0,115,117,112, + 112,111,114,116,115,95,112,97,99,107,97,103,101,115,117,8, + 0,0,0,95,95,105,110,105,116,95,95,40,1,0,0,0, 117,10,0,0,0,95,95,108,111,99,97,108,115,95,95,40, 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, 95,98,111,111,116,115,116,114,97,112,62,117,20,0,0,0, - 95,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,146,2,0,0,115,16,0,0,0,16,6,6, - 2,12,4,3,1,3,1,24,13,18,5,18,5,117,20,0, - 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,99,1,0,0,0,0,0,0,0,1, - 0,0,0,4,0,0,0,66,0,0,0,115,89,0,0,0, - 124,0,0,69,101,0,0,90,1,0,100,0,0,90,2,0, - 100,1,0,90,3,0,101,4,0,100,8,0,100,2,0,100, - 3,0,132,1,0,131,1,0,90,6,0,101,4,0,100,8, - 0,100,4,0,100,5,0,132,1,0,131,1,0,90,7,0, - 101,4,0,100,8,0,100,6,0,100,7,0,132,1,0,131, - 1,0,90,8,0,100,8,0,83,40,9,0,0,0,117,10, - 0,0,0,80,97,116,104,70,105,110,100,101,114,117,63,0, - 0,0,77,101,116,97,32,112,97,116,104,32,102,105,110,100, - 101,114,32,102,111,114,32,115,121,115,46,40,112,97,116,104, - 124,112,97,116,104,95,104,111,111,107,115,124,112,97,116,104, - 95,105,109,112,111,114,116,101,114,95,99,97,99,104,101,41, - 46,99,3,0,0,0,0,0,0,0,4,0,0,0,12,0, - 0,0,67,0,0,0,115,104,0,0,0,124,2,0,115,18, - 0,116,0,0,106,1,0,125,2,0,110,0,0,120,79,0, - 124,2,0,68,93,44,0,125,3,0,121,14,0,124,3,0, - 124,1,0,131,1,0,83,87,113,25,0,4,116,2,0,107, - 10,0,114,68,0,1,1,1,119,25,0,89,113,25,0,88, - 113,25,0,87,116,2,0,100,1,0,106,3,0,124,1,0, - 131,1,0,100,2,0,124,1,0,131,1,1,130,1,0,100, - 3,0,83,40,4,0,0,0,117,113,0,0,0,83,101,97, - 114,99,104,32,115,101,113,117,101,110,99,101,32,111,102,32, - 104,111,111,107,115,32,102,111,114,32,97,32,102,105,110,100, - 101,114,32,102,111,114,32,39,112,97,116,104,39,46,10,10, - 32,32,32,32,32,32,32,32,73,102,32,39,104,111,111,107, - 115,39,32,105,115,32,102,97,108,115,101,32,116,104,101,110, - 32,117,115,101,32,115,121,115,46,112,97,116,104,95,104,111, - 111,107,115,46,10,10,32,32,32,32,32,32,32,32,117,26, - 0,0,0,110,111,32,112,97,116,104,32,104,111,111,107,32, - 102,111,117,110,100,32,102,111,114,32,123,48,125,117,4,0, - 0,0,112,97,116,104,78,40,4,0,0,0,117,3,0,0, - 0,115,121,115,117,10,0,0,0,112,97,116,104,95,104,111, - 111,107,115,117,11,0,0,0,73,109,112,111,114,116,69,114, - 114,111,114,117,6,0,0,0,102,111,114,109,97,116,40,4, - 0,0,0,117,3,0,0,0,99,108,115,117,4,0,0,0, - 112,97,116,104,117,5,0,0,0,104,111,111,107,115,117,4, - 0,0,0,104,111,111,107,40,0,0,0,0,40,0,0,0, + 95,83,111,117,114,99,101,70,105,110,100,101,114,68,101,116, + 97,105,108,115,80,3,0,0,115,6,0,0,0,16,2,6, + 1,6,2,117,20,0,0,0,95,83,111,117,114,99,101,70, + 105,110,100,101,114,68,101,116,97,105,108,115,99,1,0,0, + 0,0,0,0,0,1,0,0,0,2,0,0,0,66,0,0, + 0,115,44,0,0,0,124,0,0,69,101,0,0,90,1,0, + 100,0,0,90,2,0,101,3,0,90,4,0,100,4,0,90, + 6,0,100,1,0,100,2,0,132,0,0,90,7,0,100,3, + 0,83,40,5,0,0,0,117,24,0,0,0,95,83,111,117, + 114,99,101,108,101,115,115,70,105,110,100,101,114,68,101,116, + 97,105,108,115,99,1,0,0,0,0,0,0,0,1,0,0, + 0,2,0,0,0,67,0,0,0,115,22,0,0,0,116,0, + 0,116,1,0,106,2,0,131,1,0,124,0,0,95,3,0, + 100,0,0,83,40,1,0,0,0,78,40,4,0,0,0,117, + 12,0,0,0,95,115,117,102,102,105,120,95,108,105,115,116, + 117,4,0,0,0,95,105,109,112,117,11,0,0,0,80,89, + 95,67,79,77,80,73,76,69,68,117,8,0,0,0,115,117, + 102,102,105,120,101,115,40,1,0,0,0,117,4,0,0,0, + 115,101,108,102,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,8,0,0,0,95,95,105,110,105,116,95,95,93,3,0, + 0,115,2,0,0,0,0,1,117,33,0,0,0,95,83,111, + 117,114,99,101,108,101,115,115,70,105,110,100,101,114,68,101, + 116,97,105,108,115,46,95,95,105,110,105,116,95,95,78,84, + 40,8,0,0,0,117,8,0,0,0,95,95,110,97,109,101, + 95,95,117,10,0,0,0,95,95,109,111,100,117,108,101,95, + 95,117,12,0,0,0,95,95,113,117,97,108,110,97,109,101, + 95,95,117,21,0,0,0,95,83,111,117,114,99,101,108,101, + 115,115,70,105,108,101,76,111,97,100,101,114,117,6,0,0, + 0,108,111,97,100,101,114,117,4,0,0,0,84,114,117,101, + 117,17,0,0,0,115,117,112,112,111,114,116,115,95,112,97, + 99,107,97,103,101,115,117,8,0,0,0,95,95,105,110,105, + 116,95,95,40,1,0,0,0,117,10,0,0,0,95,95,108, + 111,99,97,108,115,95,95,40,0,0,0,0,40,0,0,0, 0,117,29,0,0,0,60,102,114,111,122,101,110,32,105,109, 112,111,114,116,108,105,98,46,95,98,111,111,116,115,116,114, - 97,112,62,117,11,0,0,0,95,112,97,116,104,95,104,111, - 111,107,115,195,2,0,0,115,18,0,0,0,0,7,6,1, - 12,1,13,1,3,1,14,1,13,1,12,2,18,1,117,22, - 0,0,0,80,97,116,104,70,105,110,100,101,114,46,95,112, - 97,116,104,95,104,111,111,107,115,99,3,0,0,0,0,0, - 0,0,4,0,0,0,12,0,0,0,67,0,0,0,115,137, - 0,0,0,124,1,0,100,1,0,107,2,0,114,21,0,100, - 2,0,125,1,0,110,0,0,121,17,0,116,0,0,106,1, - 0,124,1,0,25,125,3,0,87,110,46,0,4,116,2,0, - 107,10,0,114,86,0,1,1,1,124,0,0,106,3,0,124, - 1,0,131,1,0,125,3,0,124,3,0,116,0,0,106,1, - 0,124,1,0,60,89,110,47,0,88,124,3,0,100,3,0, - 107,8,0,114,133,0,124,2,0,114,133,0,124,2,0,124, - 1,0,131,1,0,125,3,0,124,3,0,116,0,0,106,1, - 0,124,1,0,60,110,0,0,124,3,0,83,40,4,0,0, - 0,117,199,1,0,0,71,101,116,32,116,104,101,32,102,105, - 110,100,101,114,32,102,111,114,32,116,104,101,32,112,97,116, - 104,32,102,114,111,109,32,115,121,115,46,112,97,116,104,95, - 105,109,112,111,114,116,101,114,95,99,97,99,104,101,46,10, - 10,32,32,32,32,32,32,32,32,73,102,32,116,104,101,32, - 112,97,116,104,32,105,115,32,110,111,116,32,105,110,32,116, - 104,101,32,99,97,99,104,101,44,32,102,105,110,100,32,116, - 104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,102, - 105,110,100,101,114,32,97,110,100,32,99,97,99,104,101,10, - 32,32,32,32,32,32,32,32,105,116,46,32,73,102,32,78, - 111,110,101,32,105,115,32,99,97,99,104,101,100,44,32,103, - 101,116,32,116,104,101,32,100,101,102,97,117,108,116,32,102, - 105,110,100,101,114,32,97,110,100,32,99,97,99,104,101,32, - 116,104,97,116,10,32,32,32,32,32,32,32,32,40,105,102, - 32,97,112,112,108,105,99,97,98,108,101,41,46,10,10,32, - 32,32,32,32,32,32,32,66,101,99,97,117,115,101,32,111, - 102,32,78,117,108,108,73,109,112,111,114,116,101,114,44,32, - 115,111,109,101,32,102,105,110,100,101,114,32,115,104,111,117, - 108,100,32,98,101,32,114,101,116,117,114,110,101,100,46,32, - 84,104,101,32,111,110,108,121,10,32,32,32,32,32,32,32, - 32,101,120,112,108,105,99,105,116,32,102,97,105,108,32,99, - 97,115,101,32,105,115,32,105,102,32,78,111,110,101,32,105, - 115,32,99,97,99,104,101,100,32,98,117,116,32,116,104,101, - 32,112,97,116,104,32,99,97,110,110,111,116,32,98,101,32, - 117,115,101,100,32,102,111,114,10,32,32,32,32,32,32,32, - 32,116,104,101,32,100,101,102,97,117,108,116,32,104,111,111, - 107,44,32,102,111,114,32,119,104,105,99,104,32,73,109,112, - 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, - 101,100,46,10,10,32,32,32,32,32,32,32,32,117,0,0, - 0,0,117,1,0,0,0,46,78,40,5,0,0,0,117,3, - 0,0,0,115,121,115,117,19,0,0,0,112,97,116,104,95, - 105,109,112,111,114,116,101,114,95,99,97,99,104,101,117,8, - 0,0,0,75,101,121,69,114,114,111,114,117,11,0,0,0, - 95,112,97,116,104,95,104,111,111,107,115,117,4,0,0,0, - 78,111,110,101,40,4,0,0,0,117,3,0,0,0,99,108, - 115,117,4,0,0,0,112,97,116,104,117,7,0,0,0,100, - 101,102,97,117,108,116,117,6,0,0,0,102,105,110,100,101, - 114,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,20,0, - 0,0,95,112,97,116,104,95,105,109,112,111,114,116,101,114, - 95,99,97,99,104,101,213,2,0,0,115,22,0,0,0,0, - 13,12,1,9,1,3,1,17,1,13,1,15,1,18,2,18, - 2,12,1,16,1,117,31,0,0,0,80,97,116,104,70,105, - 110,100,101,114,46,95,112,97,116,104,95,105,109,112,111,114, - 116,101,114,95,99,97,99,104,101,99,3,0,0,0,0,0, - 0,0,6,0,0,0,12,0,0,0,67,0,0,0,115,120, - 0,0,0,124,2,0,115,18,0,116,0,0,106,1,0,125, - 2,0,110,0,0,120,95,0,124,2,0,68,93,83,0,125, - 3,0,121,19,0,124,0,0,106,2,0,124,3,0,131,1, - 0,125,4,0,87,110,21,0,4,116,3,0,107,10,0,114, - 73,0,1,1,1,119,25,0,89,110,1,0,88,124,4,0, - 114,25,0,124,4,0,106,4,0,124,1,0,131,1,0,125, - 5,0,124,5,0,114,108,0,124,5,0,83,113,25,0,113, - 25,0,87,100,1,0,83,100,1,0,83,40,2,0,0,0, - 117,98,0,0,0,70,105,110,100,32,116,104,101,32,109,111, - 100,117,108,101,32,111,110,32,115,121,115,46,112,97,116,104, - 32,111,114,32,39,112,97,116,104,39,32,98,97,115,101,100, - 32,111,110,32,115,121,115,46,112,97,116,104,95,104,111,111, - 107,115,32,97,110,100,10,32,32,32,32,32,32,32,32,115, - 121,115,46,112,97,116,104,95,105,109,112,111,114,116,101,114, - 95,99,97,99,104,101,46,78,40,6,0,0,0,117,3,0, - 0,0,115,121,115,117,4,0,0,0,112,97,116,104,117,20, - 0,0,0,95,112,97,116,104,95,105,109,112,111,114,116,101, - 114,95,99,97,99,104,101,117,11,0,0,0,73,109,112,111, - 114,116,69,114,114,111,114,117,11,0,0,0,102,105,110,100, - 95,109,111,100,117,108,101,117,4,0,0,0,78,111,110,101, - 40,6,0,0,0,117,3,0,0,0,99,108,115,117,8,0, - 0,0,102,117,108,108,110,97,109,101,117,4,0,0,0,112, - 97,116,104,117,5,0,0,0,101,110,116,114,121,117,6,0, - 0,0,102,105,110,100,101,114,117,6,0,0,0,108,111,97, - 100,101,114,40,0,0,0,0,40,0,0,0,0,117,29,0, - 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, - 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 11,0,0,0,102,105,110,100,95,109,111,100,117,108,101,240, - 2,0,0,115,24,0,0,0,0,4,6,1,12,1,13,1, - 3,1,19,1,13,1,8,1,6,1,15,1,6,1,11,2, - 117,22,0,0,0,80,97,116,104,70,105,110,100,101,114,46, - 102,105,110,100,95,109,111,100,117,108,101,78,40,9,0,0, - 0,117,8,0,0,0,95,95,110,97,109,101,95,95,117,10, - 0,0,0,95,95,109,111,100,117,108,101,95,95,117,12,0, - 0,0,95,95,113,117,97,108,110,97,109,101,95,95,117,7, - 0,0,0,95,95,100,111,99,95,95,117,11,0,0,0,99, - 108,97,115,115,109,101,116,104,111,100,117,4,0,0,0,78, - 111,110,101,117,11,0,0,0,95,112,97,116,104,95,104,111, - 111,107,115,117,20,0,0,0,95,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,117,11,0,0, - 0,102,105,110,100,95,109,111,100,117,108,101,40,1,0,0, - 0,117,10,0,0,0,95,95,108,111,99,97,108,115,95,95, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,10,0,0, - 0,80,97,116,104,70,105,110,100,101,114,191,2,0,0,115, - 14,0,0,0,16,2,6,2,3,1,18,17,3,1,18,26, - 3,1,117,10,0,0,0,80,97,116,104,70,105,110,100,101, - 114,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, - 0,0,66,0,0,0,115,74,0,0,0,124,0,0,69,101, - 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, - 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, - 100,5,0,132,0,0,90,5,0,100,6,0,100,7,0,132, - 0,0,90,6,0,100,8,0,100,9,0,132,0,0,90,7, - 0,100,10,0,83,40,11,0,0,0,117,11,0,0,0,95, - 70,105,108,101,70,105,110,100,101,114,117,171,0,0,0,70, - 105,108,101,45,98,97,115,101,100,32,102,105,110,100,101,114, - 46,10,10,32,32,32,32,67,111,110,115,116,114,117,99,116, - 111,114,32,116,97,107,101,115,32,97,32,108,105,115,116,32, - 111,102,32,111,98,106,101,99,116,115,32,100,101,116,97,105, - 108,105,110,103,32,119,104,97,116,32,102,105,108,101,32,101, - 120,116,101,110,115,105,111,110,115,32,116,104,101,105,114,10, - 32,32,32,32,108,111,97,100,101,114,32,115,117,112,112,111, - 114,116,115,32,97,108,111,110,103,32,119,105,116,104,32,119, - 104,101,116,104,101,114,32,105,116,32,99,97,110,32,98,101, - 32,117,115,101,100,32,102,111,114,32,97,32,112,97,99,107, - 97,103,101,46,10,10,32,32,32,32,99,2,0,0,0,0, - 0,0,0,5,0,0,0,5,0,0,0,7,0,0,0,115, - 181,0,0,0,103,0,0,125,3,0,103,0,0,125,4,0, - 120,96,0,124,2,0,68,93,88,0,137,0,0,124,4,0, - 106,0,0,135,0,0,102,1,0,100,1,0,100,2,0,134, - 0,0,136,0,0,106,1,0,68,131,1,0,131,1,0,1, - 136,0,0,106,2,0,114,19,0,124,3,0,106,0,0,135, - 0,0,102,1,0,100,3,0,100,2,0,134,0,0,136,0, - 0,106,1,0,68,131,1,0,131,1,0,1,113,19,0,113, - 19,0,87,124,3,0,124,0,0,95,3,0,124,4,0,124, - 0,0,95,4,0,124,1,0,112,138,0,100,4,0,124,0, - 0,95,5,0,100,7,0,124,0,0,95,6,0,116,7,0, - 131,0,0,124,0,0,95,8,0,116,7,0,131,0,0,124, - 0,0,95,9,0,100,6,0,83,40,8,0,0,0,117,31, - 0,0,0,73,110,105,116,105,97,108,105,122,101,32,119,105, - 116,104,32,102,105,110,100,101,114,32,100,101,116,97,105,108, - 115,46,99,1,0,0,0,0,0,0,0,2,0,0,0,3, - 0,0,0,51,0,0,0,115,30,0,0,0,124,0,0,93, - 20,0,125,1,0,124,1,0,136,0,0,106,0,0,102,2, - 0,86,1,113,3,0,100,0,0,83,40,1,0,0,0,78, - 40,1,0,0,0,117,6,0,0,0,108,111,97,100,101,114, - 40,2,0,0,0,117,2,0,0,0,46,48,117,6,0,0, - 0,115,117,102,102,105,120,40,1,0,0,0,117,6,0,0, - 0,100,101,116,97,105,108,40,0,0,0,0,117,29,0,0, - 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,9, - 0,0,0,60,103,101,110,101,120,112,114,62,17,3,0,0, - 115,2,0,0,0,6,0,117,39,0,0,0,95,70,105,108, - 101,70,105,110,100,101,114,46,95,95,105,110,105,116,95,95, - 46,60,108,111,99,97,108,115,62,46,60,103,101,110,101,120, - 112,114,62,99,1,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,51,0,0,0,115,30,0,0,0,124,0,0, - 93,20,0,125,1,0,124,1,0,136,0,0,106,0,0,102, - 2,0,86,1,113,3,0,100,0,0,83,40,1,0,0,0, - 78,40,1,0,0,0,117,6,0,0,0,108,111,97,100,101, - 114,40,2,0,0,0,117,2,0,0,0,46,48,117,6,0, - 0,0,115,117,102,102,105,120,40,1,0,0,0,117,6,0, - 0,0,100,101,116,97,105,108,40,0,0,0,0,117,29,0, - 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, - 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 9,0,0,0,60,103,101,110,101,120,112,114,62,19,3,0, - 0,115,2,0,0,0,6,1,117,1,0,0,0,46,105,1, - 0,0,0,78,105,255,255,255,255,40,10,0,0,0,117,6, - 0,0,0,101,120,116,101,110,100,117,8,0,0,0,115,117, - 102,102,105,120,101,115,117,17,0,0,0,115,117,112,112,111, - 114,116,115,95,112,97,99,107,97,103,101,115,117,8,0,0, - 0,112,97,99,107,97,103,101,115,117,7,0,0,0,109,111, - 100,117,108,101,115,117,4,0,0,0,112,97,116,104,117,11, - 0,0,0,95,112,97,116,104,95,109,116,105,109,101,117,3, - 0,0,0,115,101,116,117,11,0,0,0,95,112,97,116,104, - 95,99,97,99,104,101,117,19,0,0,0,95,114,101,108,97, - 120,101,100,95,112,97,116,104,95,99,97,99,104,101,40,5, - 0,0,0,117,4,0,0,0,115,101,108,102,117,4,0,0, - 0,112,97,116,104,117,7,0,0,0,100,101,116,97,105,108, - 115,117,8,0,0,0,112,97,99,107,97,103,101,115,117,7, - 0,0,0,109,111,100,117,108,101,115,40,0,0,0,0,40, - 1,0,0,0,117,6,0,0,0,100,101,116,97,105,108,117, - 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, - 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,8,0,0,0,95,95,105,110,105,116,95,95,12,3, - 0,0,115,26,0,0,0,0,2,6,1,6,1,13,1,35, - 1,9,1,21,1,21,1,9,1,9,2,15,1,9,1,12, - 1,117,20,0,0,0,95,70,105,108,101,70,105,110,100,101, - 114,46,95,95,105,110,105,116,95,95,99,1,0,0,0,0, - 0,0,0,1,0,0,0,2,0,0,0,67,0,0,0,115, - 13,0,0,0,100,3,0,124,0,0,95,0,0,100,2,0, - 83,40,4,0,0,0,117,31,0,0,0,73,110,118,97,108, - 105,100,97,116,101,32,116,104,101,32,100,105,114,101,99,116, - 111,114,121,32,109,116,105,109,101,46,105,1,0,0,0,78, - 105,255,255,255,255,40,1,0,0,0,117,11,0,0,0,95, - 112,97,116,104,95,109,116,105,109,101,40,1,0,0,0,117, - 4,0,0,0,115,101,108,102,40,0,0,0,0,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,17,0,0,0,105,110,118,97,108,105,100, - 97,116,101,95,99,97,99,104,101,115,29,3,0,0,115,2, - 0,0,0,0,2,117,29,0,0,0,95,70,105,108,101,70, - 105,110,100,101,114,46,105,110,118,97,108,105,100,97,116,101, - 95,99,97,99,104,101,115,99,2,0,0,0,0,0,0,0, - 12,0,0,0,13,0,0,0,67,0,0,0,115,151,1,0, - 0,124,1,0,106,0,0,100,1,0,131,1,0,100,2,0, - 25,125,2,0,121,25,0,116,1,0,106,2,0,124,0,0, - 106,3,0,131,1,0,106,4,0,125,3,0,87,110,24,0, - 4,116,5,0,107,10,0,114,70,0,1,1,1,100,6,0, - 125,3,0,89,110,1,0,88,124,3,0,124,0,0,106,6, - 0,107,3,0,114,108,0,124,0,0,106,7,0,131,0,0, - 1,124,3,0,124,0,0,95,6,0,110,0,0,116,8,0, - 131,0,0,114,141,0,124,0,0,106,9,0,125,4,0,124, - 2,0,106,10,0,131,0,0,125,5,0,110,15,0,124,0, - 0,106,11,0,125,4,0,124,2,0,125,5,0,124,5,0, - 124,4,0,107,6,0,114,55,1,116,12,0,124,0,0,106, - 3,0,124,2,0,131,2,0,125,6,0,116,13,0,124,6, - 0,131,1,0,114,55,1,120,107,0,124,0,0,106,14,0, - 68,93,62,0,92,2,0,125,7,0,125,8,0,100,4,0, - 124,7,0,23,125,9,0,116,12,0,124,6,0,124,9,0, - 131,2,0,125,10,0,116,15,0,124,10,0,131,1,0,114, - 208,0,124,8,0,124,1,0,124,10,0,131,2,0,83,113, - 208,0,87,100,5,0,125,11,0,116,16,0,106,17,0,124, - 11,0,106,18,0,124,6,0,131,1,0,116,19,0,131,2, - 0,1,113,55,1,110,0,0,120,89,0,124,0,0,106,20, - 0,68,93,78,0,92,2,0,125,7,0,125,8,0,124,5, - 0,124,7,0,23,124,4,0,107,6,0,114,65,1,116,12, - 0,124,0,0,106,3,0,124,2,0,124,7,0,23,131,2, - 0,125,10,0,116,15,0,124,10,0,131,1,0,114,143,1, - 124,8,0,124,1,0,124,10,0,131,2,0,83,113,65,1, - 113,65,1,87,100,7,0,83,40,8,0,0,0,117,46,0, - 0,0,84,114,121,32,116,111,32,102,105,110,100,32,97,32, - 108,111,97,100,101,114,32,102,111,114,32,116,104,101,32,115, - 112,101,99,105,102,105,101,100,32,109,111,100,117,108,101,46, - 117,1,0,0,0,46,105,2,0,0,0,105,1,0,0,0, - 117,8,0,0,0,95,95,105,110,105,116,95,95,117,44,0, - 0,0,78,111,116,32,105,109,112,111,114,116,105,110,103,32, - 100,105,114,101,99,116,111,114,121,32,123,125,58,32,109,105, - 115,115,105,110,103,32,95,95,105,110,105,116,95,95,105,255, - 255,255,255,78,40,22,0,0,0,117,10,0,0,0,114,112, - 97,114,116,105,116,105,111,110,117,3,0,0,0,95,111,115, - 117,4,0,0,0,115,116,97,116,117,4,0,0,0,112,97, - 116,104,117,8,0,0,0,115,116,95,109,116,105,109,101,117, - 7,0,0,0,79,83,69,114,114,111,114,117,11,0,0,0, - 95,112,97,116,104,95,109,116,105,109,101,117,11,0,0,0, - 95,102,105,108,108,95,99,97,99,104,101,117,11,0,0,0, - 95,114,101,108,97,120,95,99,97,115,101,117,19,0,0,0, - 95,114,101,108,97,120,101,100,95,112,97,116,104,95,99,97, - 99,104,101,117,5,0,0,0,108,111,119,101,114,117,11,0, - 0,0,95,112,97,116,104,95,99,97,99,104,101,117,10,0, - 0,0,95,112,97,116,104,95,106,111,105,110,117,11,0,0, - 0,95,112,97,116,104,95,105,115,100,105,114,117,8,0,0, - 0,112,97,99,107,97,103,101,115,117,12,0,0,0,95,112, - 97,116,104,95,105,115,102,105,108,101,117,9,0,0,0,95, - 119,97,114,110,105,110,103,115,117,4,0,0,0,119,97,114, - 110,117,6,0,0,0,102,111,114,109,97,116,117,13,0,0, - 0,73,109,112,111,114,116,87,97,114,110,105,110,103,117,7, - 0,0,0,109,111,100,117,108,101,115,117,4,0,0,0,78, - 111,110,101,40,12,0,0,0,117,4,0,0,0,115,101,108, - 102,117,8,0,0,0,102,117,108,108,110,97,109,101,117,11, - 0,0,0,116,97,105,108,95,109,111,100,117,108,101,117,5, - 0,0,0,109,116,105,109,101,117,5,0,0,0,99,97,99, - 104,101,117,12,0,0,0,99,97,99,104,101,95,109,111,100, - 117,108,101,117,9,0,0,0,98,97,115,101,95,112,97,116, - 104,117,6,0,0,0,115,117,102,102,105,120,117,6,0,0, - 0,108,111,97,100,101,114,117,13,0,0,0,105,110,105,116, - 95,102,105,108,101,110,97,109,101,117,9,0,0,0,102,117, - 108,108,95,112,97,116,104,117,3,0,0,0,109,115,103,40, - 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,11,0,0,0, - 102,105,110,100,95,109,111,100,117,108,101,33,3,0,0,115, - 58,0,0,0,0,2,19,1,3,1,25,1,13,1,11,1, - 15,1,10,1,12,2,9,1,9,1,15,2,9,1,6,2, - 12,1,18,1,12,1,22,1,10,1,15,1,12,1,17,2, - 6,1,31,2,22,1,16,1,22,1,12,1,20,1,117,23, - 0,0,0,95,70,105,108,101,70,105,110,100,101,114,46,102, - 105,110,100,95,109,111,100,117,108,101,99,1,0,0,0,0, - 0,0,0,3,0,0,0,3,0,0,0,67,0,0,0,115, - 71,0,0,0,124,0,0,106,0,0,125,1,0,116,1,0, - 106,2,0,124,1,0,131,1,0,125,2,0,116,3,0,124, - 2,0,131,1,0,124,0,0,95,4,0,116,3,0,100,1, - 0,100,2,0,132,0,0,124,2,0,68,131,1,0,131,1, - 0,124,0,0,95,5,0,100,3,0,83,40,4,0,0,0, - 117,68,0,0,0,70,105,108,108,32,116,104,101,32,99,97, - 99,104,101,32,111,102,32,112,111,116,101,110,116,105,97,108, - 32,109,111,100,117,108,101,115,32,97,110,100,32,112,97,99, - 107,97,103,101,115,32,102,111,114,32,116,104,105,115,32,100, - 105,114,101,99,116,111,114,121,46,99,1,0,0,0,0,0, - 0,0,2,0,0,0,2,0,0,0,115,0,0,0,115,27, - 0,0,0,124,0,0,93,17,0,125,1,0,124,1,0,106, - 0,0,131,0,0,86,1,113,3,0,100,0,0,83,40,1, - 0,0,0,78,40,1,0,0,0,117,5,0,0,0,108,111, - 119,101,114,40,2,0,0,0,117,2,0,0,0,46,48,117, - 2,0,0,0,102,110,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,9,0,0,0,60,103,101,110,101,120,112,114,62, - 77,3,0,0,115,2,0,0,0,6,0,117,42,0,0,0, - 95,70,105,108,101,70,105,110,100,101,114,46,95,102,105,108, - 108,95,99,97,99,104,101,46,60,108,111,99,97,108,115,62, - 46,60,103,101,110,101,120,112,114,62,78,40,6,0,0,0, - 117,4,0,0,0,112,97,116,104,117,3,0,0,0,95,111, - 115,117,7,0,0,0,108,105,115,116,100,105,114,117,3,0, - 0,0,115,101,116,117,11,0,0,0,95,112,97,116,104,95, - 99,97,99,104,101,117,19,0,0,0,95,114,101,108,97,120, - 101,100,95,112,97,116,104,95,99,97,99,104,101,40,3,0, - 0,0,117,4,0,0,0,115,101,108,102,117,4,0,0,0, - 112,97,116,104,117,8,0,0,0,99,111,110,116,101,110,116, - 115,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,11,0, - 0,0,95,102,105,108,108,95,99,97,99,104,101,70,3,0, - 0,115,8,0,0,0,0,2,9,1,15,3,15,1,117,23, - 0,0,0,95,70,105,108,101,70,105,110,100,101,114,46,95, - 102,105,108,108,95,99,97,99,104,101,78,40,8,0,0,0, - 117,8,0,0,0,95,95,110,97,109,101,95,95,117,10,0, - 0,0,95,95,109,111,100,117,108,101,95,95,117,12,0,0, - 0,95,95,113,117,97,108,110,97,109,101,95,95,117,7,0, - 0,0,95,95,100,111,99,95,95,117,8,0,0,0,95,95, - 105,110,105,116,95,95,117,17,0,0,0,105,110,118,97,108, - 105,100,97,116,101,95,99,97,99,104,101,115,117,11,0,0, - 0,102,105,110,100,95,109,111,100,117,108,101,117,11,0,0, - 0,95,102,105,108,108,95,99,97,99,104,101,40,1,0,0, - 0,117,10,0,0,0,95,95,108,111,99,97,108,115,95,95, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,11,0,0, - 0,95,70,105,108,101,70,105,110,100,101,114,3,3,0,0, - 115,10,0,0,0,16,7,6,2,12,17,12,4,12,37,117, - 11,0,0,0,95,70,105,108,101,70,105,110,100,101,114,99, - 1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, - 66,0,0,0,115,44,0,0,0,124,0,0,69,101,0,0, - 90,1,0,100,0,0,90,2,0,101,3,0,90,4,0,100, - 4,0,90,6,0,100,1,0,100,2,0,132,0,0,90,7, - 0,100,3,0,83,40,5,0,0,0,117,20,0,0,0,95, - 83,111,117,114,99,101,70,105,110,100,101,114,68,101,116,97, + 97,112,62,117,24,0,0,0,95,83,111,117,114,99,101,108, + 101,115,115,70,105,110,100,101,114,68,101,116,97,105,108,115, + 88,3,0,0,115,6,0,0,0,16,2,6,1,6,2,117, + 24,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, + 105,110,100,101,114,68,101,116,97,105,108,115,99,1,0,0, + 0,0,0,0,0,1,0,0,0,2,0,0,0,66,0,0, + 0,115,44,0,0,0,124,0,0,69,101,0,0,90,1,0, + 100,0,0,90,2,0,101,3,0,90,4,0,100,4,0,90, + 6,0,100,1,0,100,2,0,132,0,0,90,7,0,100,3, + 0,83,40,5,0,0,0,117,23,0,0,0,95,69,120,116, + 101,110,115,105,111,110,70,105,110,100,101,114,68,101,116,97, 105,108,115,99,1,0,0,0,0,0,0,0,1,0,0,0, 2,0,0,0,67,0,0,0,115,22,0,0,0,116,0,0, 116,1,0,106,2,0,131,1,0,124,0,0,95,3,0,100, 0,0,83,40,1,0,0,0,78,40,4,0,0,0,117,12, 0,0,0,95,115,117,102,102,105,120,95,108,105,115,116,117, - 4,0,0,0,95,105,109,112,117,9,0,0,0,80,89,95, - 83,79,85,82,67,69,117,8,0,0,0,115,117,102,102,105, - 120,101,115,40,1,0,0,0,117,4,0,0,0,115,101,108, - 102,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, + 4,0,0,0,95,105,109,112,117,11,0,0,0,67,95,69, + 88,84,69,78,83,73,79,78,117,8,0,0,0,115,117,102, + 102,105,120,101,115,40,1,0,0,0,117,4,0,0,0,115, + 101,108,102,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 8,0,0,0,95,95,105,110,105,116,95,95,102,3,0,0, + 115,2,0,0,0,0,1,117,32,0,0,0,95,69,120,116, + 101,110,115,105,111,110,70,105,110,100,101,114,68,101,116,97, + 105,108,115,46,95,95,105,110,105,116,95,95,78,70,40,8, + 0,0,0,117,8,0,0,0,95,95,110,97,109,101,95,95, + 117,10,0,0,0,95,95,109,111,100,117,108,101,95,95,117, + 12,0,0,0,95,95,113,117,97,108,110,97,109,101,95,95, + 117,20,0,0,0,95,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,117,6,0,0,0,108,111, + 97,100,101,114,117,5,0,0,0,70,97,108,115,101,117,17, + 0,0,0,115,117,112,112,111,114,116,115,95,112,97,99,107, + 97,103,101,115,117,8,0,0,0,95,95,105,110,105,116,95, + 95,40,1,0,0,0,117,10,0,0,0,95,95,108,111,99, + 97,108,115,95,95,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,23,0,0,0,95,69,120,116,101,110,115,105,111,110, + 70,105,110,100,101,114,68,101,116,97,105,108,115,97,3,0, + 0,115,6,0,0,0,16,2,6,1,6,2,117,23,0,0, + 0,95,69,120,116,101,110,115,105,111,110,70,105,110,100,101, + 114,68,101,116,97,105,108,115,99,1,0,0,0,0,0,0, + 0,1,0,0,0,5,0,0,0,67,0,0,0,115,62,0, + 0,0,116,0,0,124,0,0,131,1,0,114,40,0,116,1, + 0,124,0,0,116,2,0,131,0,0,116,3,0,131,0,0, + 116,4,0,131,0,0,131,4,0,83,116,5,0,100,1,0, + 100,2,0,124,0,0,131,1,1,130,1,0,100,3,0,83, + 40,4,0,0,0,117,55,0,0,0,73,102,32,116,104,101, + 32,112,97,116,104,32,105,115,32,97,32,100,105,114,101,99, + 116,111,114,121,44,32,114,101,116,117,114,110,32,97,32,102, + 105,108,101,45,98,97,115,101,100,32,102,105,110,100,101,114, + 46,117,30,0,0,0,111,110,108,121,32,100,105,114,101,99, + 116,111,114,105,101,115,32,97,114,101,32,115,117,112,112,111, + 114,116,101,100,117,4,0,0,0,112,97,116,104,78,40,6, + 0,0,0,117,11,0,0,0,95,112,97,116,104,95,105,115, + 100,105,114,117,11,0,0,0,95,70,105,108,101,70,105,110, + 100,101,114,117,23,0,0,0,95,69,120,116,101,110,115,105, + 111,110,70,105,110,100,101,114,68,101,116,97,105,108,115,117, + 20,0,0,0,95,83,111,117,114,99,101,70,105,110,100,101, + 114,68,101,116,97,105,108,115,117,24,0,0,0,95,83,111, + 117,114,99,101,108,101,115,115,70,105,110,100,101,114,68,101, + 116,97,105,108,115,117,11,0,0,0,73,109,112,111,114,116, + 69,114,114,111,114,40,1,0,0,0,117,4,0,0,0,112, + 97,116,104,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 15,0,0,0,95,102,105,108,101,95,112,97,116,104,95,104, + 111,111,107,108,3,0,0,115,10,0,0,0,0,2,12,1, + 12,1,6,1,10,2,117,15,0,0,0,95,102,105,108,101, + 95,112,97,116,104,95,104,111,111,107,99,1,0,0,0,0, + 0,0,0,1,0,0,0,4,0,0,0,2,0,0,0,115, + 74,0,0,0,124,0,0,69,101,0,0,90,1,0,100,0, + 0,90,2,0,100,1,0,90,3,0,101,4,0,135,0,0, + 102,1,0,100,2,0,100,3,0,134,0,0,131,1,0,90, + 5,0,101,4,0,135,0,0,102,1,0,100,4,0,100,5, + 0,134,0,0,131,1,0,90,6,0,135,0,0,83,40,6, + 0,0,0,117,18,0,0,0,95,68,101,102,97,117,108,116, + 80,97,116,104,70,105,110,100,101,114,117,77,0,0,0,83, + 117,98,99,108,97,115,115,32,111,102,32,80,97,116,104,70, + 105,110,100,101,114,32,116,104,97,116,32,105,109,112,108,101, + 109,101,110,116,115,32,105,109,112,108,105,99,105,116,32,115, + 101,109,97,110,116,105,99,115,32,102,111,114,10,32,32,32, + 32,95,95,105,109,112,111,114,116,95,95,46,99,2,0,0, + 0,0,0,0,0,3,0,0,0,11,0,0,0,3,0,0, + 0,115,79,0,0,0,121,20,0,116,0,0,131,0,0,106, + 1,0,124,1,0,131,1,0,83,87,110,52,0,4,116,2, + 0,107,10,0,114,74,0,1,1,1,116,3,0,116,4,0, + 106,5,0,103,2,0,125,2,0,116,0,0,131,0,0,106, + 1,0,124,1,0,124,2,0,131,2,0,83,89,110,1,0, + 88,100,1,0,83,40,2,0,0,0,117,53,0,0,0,83, + 101,97,114,99,104,32,115,121,115,46,112,97,116,104,95,104, + 111,111,107,115,32,97,115,32,119,101,108,108,32,97,115,32, + 105,109,112,108,105,99,105,116,32,112,97,116,104,32,104,111, + 111,107,115,46,78,40,6,0,0,0,117,5,0,0,0,115, + 117,112,101,114,117,11,0,0,0,95,112,97,116,104,95,104, + 111,111,107,115,117,11,0,0,0,73,109,112,111,114,116,69, + 114,114,111,114,117,18,0,0,0,95,68,69,70,65,85,76, + 84,95,80,65,84,72,95,72,79,79,75,117,4,0,0,0, + 95,105,109,112,117,12,0,0,0,78,117,108,108,73,109,112, + 111,114,116,101,114,40,3,0,0,0,117,3,0,0,0,99, + 108,115,117,4,0,0,0,112,97,116,104,117,14,0,0,0, + 105,109,112,108,105,99,105,116,95,104,111,111,107,115,40,1, + 0,0,0,117,10,0,0,0,64,95,95,99,108,97,115,115, + 95,95,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,11,0,0,0,95,112, + 97,116,104,95,104,111,111,107,115,125,3,0,0,115,10,0, + 0,0,0,3,3,1,20,1,13,1,15,1,117,30,0,0, + 0,95,68,101,102,97,117,108,116,80,97,116,104,70,105,110, + 100,101,114,46,95,112,97,116,104,95,104,111,111,107,115,99, + 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 3,0,0,0,115,19,0,0,0,116,0,0,131,0,0,106, + 1,0,124,1,0,116,2,0,131,2,0,83,40,1,0,0, + 0,117,81,0,0,0,85,115,101,32,116,104,101,32,100,101, + 102,97,117,108,116,32,112,97,116,104,32,104,111,111,107,32, + 119,104,101,110,32,78,111,110,101,32,105,115,32,115,116,111, + 114,101,100,32,105,110,10,32,32,32,32,32,32,32,32,115, + 121,115,46,112,97,116,104,95,105,109,112,111,114,116,101,114, + 95,99,97,99,104,101,46,40,3,0,0,0,117,5,0,0, + 0,115,117,112,101,114,117,20,0,0,0,95,112,97,116,104, + 95,105,109,112,111,114,116,101,114,95,99,97,99,104,101,117, + 18,0,0,0,95,68,69,70,65,85,76,84,95,80,65,84, + 72,95,72,79,79,75,40,2,0,0,0,117,3,0,0,0, + 99,108,115,117,4,0,0,0,112,97,116,104,40,1,0,0, + 0,117,10,0,0,0,64,95,95,99,108,97,115,115,95,95, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,20,0,0,0,95,112,97,116, + 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, + 134,3,0,0,115,2,0,0,0,0,4,117,39,0,0,0, + 95,68,101,102,97,117,108,116,80,97,116,104,70,105,110,100, + 101,114,46,95,112,97,116,104,95,105,109,112,111,114,116,101, + 114,95,99,97,99,104,101,40,7,0,0,0,117,8,0,0, + 0,95,95,110,97,109,101,95,95,117,10,0,0,0,95,95, + 109,111,100,117,108,101,95,95,117,12,0,0,0,95,95,113, + 117,97,108,110,97,109,101,95,95,117,7,0,0,0,95,95, + 100,111,99,95,95,117,11,0,0,0,99,108,97,115,115,109, + 101,116,104,111,100,117,11,0,0,0,95,112,97,116,104,95, + 104,111,111,107,115,117,20,0,0,0,95,112,97,116,104,95, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,40,1, + 0,0,0,117,10,0,0,0,95,95,108,111,99,97,108,115, + 95,95,40,0,0,0,0,40,1,0,0,0,117,10,0,0, + 0,64,95,95,99,108,97,115,115,95,95,117,29,0,0,0, 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, - 0,0,95,95,105,110,105,116,95,95,85,3,0,0,115,2, - 0,0,0,0,1,117,29,0,0,0,95,83,111,117,114,99, - 101,70,105,110,100,101,114,68,101,116,97,105,108,115,46,95, - 95,105,110,105,116,95,95,78,84,40,8,0,0,0,117,8, - 0,0,0,95,95,110,97,109,101,95,95,117,10,0,0,0, - 95,95,109,111,100,117,108,101,95,95,117,12,0,0,0,95, - 95,113,117,97,108,110,97,109,101,95,95,117,17,0,0,0, - 95,83,111,117,114,99,101,70,105,108,101,76,111,97,100,101, - 114,117,6,0,0,0,108,111,97,100,101,114,117,4,0,0, - 0,84,114,117,101,117,17,0,0,0,115,117,112,112,111,114, - 116,115,95,112,97,99,107,97,103,101,115,117,8,0,0,0, - 95,95,105,110,105,116,95,95,40,1,0,0,0,117,10,0, - 0,0,95,95,108,111,99,97,108,115,95,95,40,0,0,0, - 0,40,0,0,0,0,117,29,0,0,0,60,102,114,111,122, - 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, - 111,116,115,116,114,97,112,62,117,20,0,0,0,95,83,111, - 117,114,99,101,70,105,110,100,101,114,68,101,116,97,105,108, - 115,80,3,0,0,115,6,0,0,0,16,2,6,1,6,2, - 117,20,0,0,0,95,83,111,117,114,99,101,70,105,110,100, - 101,114,68,101,116,97,105,108,115,99,1,0,0,0,0,0, - 0,0,1,0,0,0,2,0,0,0,66,0,0,0,115,44, - 0,0,0,124,0,0,69,101,0,0,90,1,0,100,0,0, - 90,2,0,101,3,0,90,4,0,100,4,0,90,6,0,100, - 1,0,100,2,0,132,0,0,90,7,0,100,3,0,83,40, - 5,0,0,0,117,24,0,0,0,95,83,111,117,114,99,101, - 108,101,115,115,70,105,110,100,101,114,68,101,116,97,105,108, - 115,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, - 0,0,67,0,0,0,115,22,0,0,0,116,0,0,116,1, - 0,106,2,0,131,1,0,124,0,0,95,3,0,100,0,0, - 83,40,1,0,0,0,78,40,4,0,0,0,117,12,0,0, - 0,95,115,117,102,102,105,120,95,108,105,115,116,117,4,0, - 0,0,95,105,109,112,117,11,0,0,0,80,89,95,67,79, - 77,80,73,76,69,68,117,8,0,0,0,115,117,102,102,105, - 120,101,115,40,1,0,0,0,117,4,0,0,0,115,101,108, - 102,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,8,0, - 0,0,95,95,105,110,105,116,95,95,93,3,0,0,115,2, - 0,0,0,0,1,117,33,0,0,0,95,83,111,117,114,99, - 101,108,101,115,115,70,105,110,100,101,114,68,101,116,97,105, - 108,115,46,95,95,105,110,105,116,95,95,78,84,40,8,0, - 0,0,117,8,0,0,0,95,95,110,97,109,101,95,95,117, - 10,0,0,0,95,95,109,111,100,117,108,101,95,95,117,12, - 0,0,0,95,95,113,117,97,108,110,97,109,101,95,95,117, - 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, - 105,108,101,76,111,97,100,101,114,117,6,0,0,0,108,111, - 97,100,101,114,117,4,0,0,0,84,114,117,101,117,17,0, - 0,0,115,117,112,112,111,114,116,115,95,112,97,99,107,97, - 103,101,115,117,8,0,0,0,95,95,105,110,105,116,95,95, + 98,46,95,98,111,111,116,115,116,114,97,112,62,117,18,0, + 0,0,95,68,101,102,97,117,108,116,80,97,116,104,70,105, + 110,100,101,114,120,3,0,0,115,6,0,0,0,16,3,6, + 2,24,9,117,18,0,0,0,95,68,101,102,97,117,108,116, + 80,97,116,104,70,105,110,100,101,114,99,1,0,0,0,0, + 0,0,0,1,0,0,0,2,0,0,0,66,0,0,0,115, + 50,0,0,0,124,0,0,69,101,0,0,90,1,0,100,0, + 0,90,2,0,100,1,0,90,3,0,100,2,0,100,3,0, + 132,0,0,90,4,0,100,4,0,100,5,0,132,0,0,90, + 5,0,100,6,0,83,40,7,0,0,0,117,18,0,0,0, + 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, + 120,116,117,36,0,0,0,67,111,110,116,101,120,116,32,109, + 97,110,97,103,101,114,32,102,111,114,32,116,104,101,32,105, + 109,112,111,114,116,32,108,111,99,107,46,99,1,0,0,0, + 0,0,0,0,1,0,0,0,1,0,0,0,67,0,0,0, + 115,14,0,0,0,116,0,0,106,1,0,131,0,0,1,100, + 1,0,83,40,2,0,0,0,117,24,0,0,0,65,99,113, + 117,105,114,101,32,116,104,101,32,105,109,112,111,114,116,32, + 108,111,99,107,46,78,40,2,0,0,0,117,4,0,0,0, + 95,105,109,112,117,12,0,0,0,97,99,113,117,105,114,101, + 95,108,111,99,107,40,1,0,0,0,117,4,0,0,0,115, + 101,108,102,40,0,0,0,0,40,0,0,0,0,117,29,0, + 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, + 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, + 9,0,0,0,95,95,101,110,116,101,114,95,95,145,3,0, + 0,115,2,0,0,0,0,2,117,28,0,0,0,95,73,109, + 112,111,114,116,76,111,99,107,67,111,110,116,101,120,116,46, + 95,95,101,110,116,101,114,95,95,99,4,0,0,0,0,0, + 0,0,4,0,0,0,1,0,0,0,67,0,0,0,115,14, + 0,0,0,116,0,0,106,1,0,131,0,0,1,100,1,0, + 83,40,2,0,0,0,117,60,0,0,0,82,101,108,101,97, + 115,101,32,116,104,101,32,105,109,112,111,114,116,32,108,111, + 99,107,32,114,101,103,97,114,100,108,101,115,115,32,111,102, + 32,97,110,121,32,114,97,105,115,101,100,32,101,120,99,101, + 112,116,105,111,110,115,46,78,40,2,0,0,0,117,4,0, + 0,0,95,105,109,112,117,12,0,0,0,114,101,108,101,97, + 115,101,95,108,111,99,107,40,4,0,0,0,117,4,0,0, + 0,115,101,108,102,117,8,0,0,0,101,120,99,95,116,121, + 112,101,117,9,0,0,0,101,120,99,95,118,97,108,117,101, + 117,13,0,0,0,101,120,99,95,116,114,97,99,101,98,97, + 99,107,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,8, + 0,0,0,95,95,101,120,105,116,95,95,149,3,0,0,115, + 2,0,0,0,0,2,117,27,0,0,0,95,73,109,112,111, + 114,116,76,111,99,107,67,111,110,116,101,120,116,46,95,95, + 101,120,105,116,95,95,78,40,6,0,0,0,117,8,0,0, + 0,95,95,110,97,109,101,95,95,117,10,0,0,0,95,95, + 109,111,100,117,108,101,95,95,117,12,0,0,0,95,95,113, + 117,97,108,110,97,109,101,95,95,117,7,0,0,0,95,95, + 100,111,99,95,95,117,9,0,0,0,95,95,101,110,116,101, + 114,95,95,117,8,0,0,0,95,95,101,120,105,116,95,95, 40,1,0,0,0,117,10,0,0,0,95,95,108,111,99,97, 108,115,95,95,40,0,0,0,0,40,0,0,0,0,117,29, 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, - 117,24,0,0,0,95,83,111,117,114,99,101,108,101,115,115, - 70,105,110,100,101,114,68,101,116,97,105,108,115,88,3,0, - 0,115,6,0,0,0,16,2,6,1,6,2,117,24,0,0, - 0,95,83,111,117,114,99,101,108,101,115,115,70,105,110,100, - 101,114,68,101,116,97,105,108,115,99,1,0,0,0,0,0, - 0,0,1,0,0,0,2,0,0,0,66,0,0,0,115,44, - 0,0,0,124,0,0,69,101,0,0,90,1,0,100,0,0, - 90,2,0,101,3,0,90,4,0,100,4,0,90,6,0,100, - 1,0,100,2,0,132,0,0,90,7,0,100,3,0,83,40, - 5,0,0,0,117,23,0,0,0,95,69,120,116,101,110,115, - 105,111,110,70,105,110,100,101,114,68,101,116,97,105,108,115, - 99,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0, - 0,67,0,0,0,115,22,0,0,0,116,0,0,116,1,0, - 106,2,0,131,1,0,124,0,0,95,3,0,100,0,0,83, - 40,1,0,0,0,78,40,4,0,0,0,117,12,0,0,0, - 95,115,117,102,102,105,120,95,108,105,115,116,117,4,0,0, - 0,95,105,109,112,117,11,0,0,0,67,95,69,88,84,69, - 78,83,73,79,78,117,8,0,0,0,115,117,102,102,105,120, - 101,115,40,1,0,0,0,117,4,0,0,0,115,101,108,102, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,8,0,0, - 0,95,95,105,110,105,116,95,95,102,3,0,0,115,2,0, - 0,0,0,1,117,32,0,0,0,95,69,120,116,101,110,115, - 105,111,110,70,105,110,100,101,114,68,101,116,97,105,108,115, - 46,95,95,105,110,105,116,95,95,78,70,40,8,0,0,0, - 117,8,0,0,0,95,95,110,97,109,101,95,95,117,10,0, - 0,0,95,95,109,111,100,117,108,101,95,95,117,12,0,0, - 0,95,95,113,117,97,108,110,97,109,101,95,95,117,20,0, - 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,117,6,0,0,0,108,111,97,100,101, - 114,117,5,0,0,0,70,97,108,115,101,117,17,0,0,0, - 115,117,112,112,111,114,116,115,95,112,97,99,107,97,103,101, - 115,117,8,0,0,0,95,95,105,110,105,116,95,95,40,1, - 0,0,0,117,10,0,0,0,95,95,108,111,99,97,108,115, - 95,95,40,0,0,0,0,40,0,0,0,0,117,29,0,0, + 117,18,0,0,0,95,73,109,112,111,114,116,76,111,99,107, + 67,111,110,116,101,120,116,141,3,0,0,115,6,0,0,0, + 16,2,6,2,12,4,117,18,0,0,0,95,73,109,112,111, + 114,116,76,111,99,107,67,111,110,116,101,120,116,99,3,0, + 0,0,0,0,0,0,5,0,0,0,4,0,0,0,67,0, + 0,0,115,91,0,0,0,124,1,0,106,0,0,100,1,0, + 124,2,0,100,2,0,24,131,2,0,125,3,0,116,1,0, + 124,3,0,131,1,0,124,2,0,107,0,0,114,55,0,116, + 2,0,100,3,0,131,1,0,130,1,0,110,0,0,124,3, + 0,100,4,0,25,125,4,0,124,0,0,114,87,0,100,5, + 0,106,3,0,124,4,0,124,0,0,131,2,0,83,124,4, + 0,83,40,6,0,0,0,117,50,0,0,0,82,101,115,111, + 108,118,101,32,97,32,114,101,108,97,116,105,118,101,32,109, + 111,100,117,108,101,32,110,97,109,101,32,116,111,32,97,110, + 32,97,98,115,111,108,117,116,101,32,111,110,101,46,117,1, + 0,0,0,46,105,1,0,0,0,117,50,0,0,0,97,116, + 116,101,109,112,116,101,100,32,114,101,108,97,116,105,118,101, + 32,105,109,112,111,114,116,32,98,101,121,111,110,100,32,116, + 111,112,45,108,101,118,101,108,32,112,97,99,107,97,103,101, + 105,0,0,0,0,117,7,0,0,0,123,48,125,46,123,49, + 125,40,4,0,0,0,117,6,0,0,0,114,115,112,108,105, + 116,117,3,0,0,0,108,101,110,117,10,0,0,0,86,97, + 108,117,101,69,114,114,111,114,117,6,0,0,0,102,111,114, + 109,97,116,40,5,0,0,0,117,4,0,0,0,110,97,109, + 101,117,7,0,0,0,112,97,99,107,97,103,101,117,5,0, + 0,0,108,101,118,101,108,117,4,0,0,0,98,105,116,115, + 117,4,0,0,0,98,97,115,101,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,13,0,0,0,95,114,101,115,111,108, + 118,101,95,110,97,109,101,154,3,0,0,115,10,0,0,0, + 0,2,22,1,18,1,15,1,10,1,117,13,0,0,0,95, + 114,101,115,111,108,118,101,95,110,97,109,101,99,2,0,0, + 0,0,0,0,0,5,0,0,0,4,0,0,0,67,0,0, + 0,115,104,0,0,0,116,0,0,106,1,0,116,2,0,23, + 125,2,0,120,84,0,124,2,0,68,93,72,0,125,3,0, + 124,3,0,106,3,0,124,0,0,124,1,0,131,2,0,125, + 4,0,124,4,0,100,1,0,107,9,0,114,20,0,124,0, + 0,116,0,0,106,5,0,107,7,0,114,75,0,124,4,0, + 83,116,0,0,106,5,0,124,0,0,25,106,6,0,83,113, + 20,0,113,20,0,87,100,1,0,83,100,1,0,83,40,2, + 0,0,0,117,23,0,0,0,70,105,110,100,32,97,32,109, + 111,100,117,108,101,39,115,32,108,111,97,100,101,114,46,78, + 40,7,0,0,0,117,3,0,0,0,115,121,115,117,9,0, + 0,0,109,101,116,97,95,112,97,116,104,117,19,0,0,0, + 95,73,77,80,76,73,67,73,84,95,77,69,84,65,95,80, + 65,84,72,117,11,0,0,0,102,105,110,100,95,109,111,100, + 117,108,101,117,4,0,0,0,78,111,110,101,117,7,0,0, + 0,109,111,100,117,108,101,115,117,10,0,0,0,95,95,108, + 111,97,100,101,114,95,95,40,5,0,0,0,117,4,0,0, + 0,110,97,109,101,117,4,0,0,0,112,97,116,104,117,9, + 0,0,0,109,101,116,97,95,112,97,116,104,117,6,0,0, + 0,102,105,110,100,101,114,117,6,0,0,0,108,111,97,100, + 101,114,40,0,0,0,0,40,0,0,0,0,117,29,0,0, 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,23, - 0,0,0,95,69,120,116,101,110,115,105,111,110,70,105,110, - 100,101,114,68,101,116,97,105,108,115,97,3,0,0,115,6, - 0,0,0,16,2,6,1,6,2,117,23,0,0,0,95,69, - 120,116,101,110,115,105,111,110,70,105,110,100,101,114,68,101, - 116,97,105,108,115,99,1,0,0,0,0,0,0,0,1,0, - 0,0,5,0,0,0,67,0,0,0,115,62,0,0,0,116, - 0,0,124,0,0,131,1,0,114,40,0,116,1,0,124,0, - 0,116,2,0,131,0,0,116,3,0,131,0,0,116,4,0, - 131,0,0,131,4,0,83,116,5,0,100,1,0,100,2,0, - 124,0,0,131,1,1,130,1,0,100,3,0,83,40,4,0, - 0,0,117,55,0,0,0,73,102,32,116,104,101,32,112,97, - 116,104,32,105,115,32,97,32,100,105,114,101,99,116,111,114, - 121,44,32,114,101,116,117,114,110,32,97,32,102,105,108,101, - 45,98,97,115,101,100,32,102,105,110,100,101,114,46,117,30, - 0,0,0,111,110,108,121,32,100,105,114,101,99,116,111,114, - 105,101,115,32,97,114,101,32,115,117,112,112,111,114,116,101, - 100,117,4,0,0,0,112,97,116,104,78,40,6,0,0,0, - 117,11,0,0,0,95,112,97,116,104,95,105,115,100,105,114, - 117,11,0,0,0,95,70,105,108,101,70,105,110,100,101,114, - 117,23,0,0,0,95,69,120,116,101,110,115,105,111,110,70, - 105,110,100,101,114,68,101,116,97,105,108,115,117,20,0,0, - 0,95,83,111,117,114,99,101,70,105,110,100,101,114,68,101, - 116,97,105,108,115,117,24,0,0,0,95,83,111,117,114,99, - 101,108,101,115,115,70,105,110,100,101,114,68,101,116,97,105, - 108,115,117,11,0,0,0,73,109,112,111,114,116,69,114,114, - 111,114,40,1,0,0,0,117,4,0,0,0,112,97,116,104, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,15,0,0, - 0,95,102,105,108,101,95,112,97,116,104,95,104,111,111,107, - 108,3,0,0,115,10,0,0,0,0,2,12,1,12,1,6, - 1,10,2,117,15,0,0,0,95,102,105,108,101,95,112,97, - 116,104,95,104,111,111,107,99,1,0,0,0,0,0,0,0, - 1,0,0,0,4,0,0,0,2,0,0,0,115,74,0,0, - 0,124,0,0,69,101,0,0,90,1,0,100,0,0,90,2, - 0,100,1,0,90,3,0,101,4,0,135,0,0,102,1,0, - 100,2,0,100,3,0,134,0,0,131,1,0,90,5,0,101, - 4,0,135,0,0,102,1,0,100,4,0,100,5,0,134,0, - 0,131,1,0,90,6,0,135,0,0,83,40,6,0,0,0, - 117,18,0,0,0,95,68,101,102,97,117,108,116,80,97,116, - 104,70,105,110,100,101,114,117,77,0,0,0,83,117,98,99, - 108,97,115,115,32,111,102,32,80,97,116,104,70,105,110,100, - 101,114,32,116,104,97,116,32,105,109,112,108,101,109,101,110, - 116,115,32,105,109,112,108,105,99,105,116,32,115,101,109,97, - 110,116,105,99,115,32,102,111,114,10,32,32,32,32,95,95, - 105,109,112,111,114,116,95,95,46,99,2,0,0,0,0,0, - 0,0,3,0,0,0,11,0,0,0,3,0,0,0,115,79, - 0,0,0,121,20,0,116,0,0,131,0,0,106,1,0,124, - 1,0,131,1,0,83,87,110,52,0,4,116,2,0,107,10, - 0,114,74,0,1,1,1,116,3,0,116,4,0,106,5,0, - 103,2,0,125,2,0,116,0,0,131,0,0,106,1,0,124, - 1,0,124,2,0,131,2,0,83,89,110,1,0,88,100,1, - 0,83,40,2,0,0,0,117,53,0,0,0,83,101,97,114, - 99,104,32,115,121,115,46,112,97,116,104,95,104,111,111,107, - 115,32,97,115,32,119,101,108,108,32,97,115,32,105,109,112, - 108,105,99,105,116,32,112,97,116,104,32,104,111,111,107,115, - 46,78,40,6,0,0,0,117,5,0,0,0,115,117,112,101, - 114,117,11,0,0,0,95,112,97,116,104,95,104,111,111,107, - 115,117,11,0,0,0,73,109,112,111,114,116,69,114,114,111, - 114,117,18,0,0,0,95,68,69,70,65,85,76,84,95,80, - 65,84,72,95,72,79,79,75,117,4,0,0,0,95,105,109, - 112,117,12,0,0,0,78,117,108,108,73,109,112,111,114,116, - 101,114,40,3,0,0,0,117,3,0,0,0,99,108,115,117, - 4,0,0,0,112,97,116,104,117,14,0,0,0,105,109,112, - 108,105,99,105,116,95,104,111,111,107,115,40,1,0,0,0, - 117,10,0,0,0,64,95,95,99,108,97,115,115,95,95,40, - 0,0,0,0,117,29,0,0,0,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,117,11,0,0,0,95,112,97,116,104, - 95,104,111,111,107,115,125,3,0,0,115,10,0,0,0,0, - 3,3,1,20,1,13,1,15,1,117,30,0,0,0,95,68, - 101,102,97,117,108,116,80,97,116,104,70,105,110,100,101,114, - 46,95,112,97,116,104,95,104,111,111,107,115,99,2,0,0, - 0,0,0,0,0,2,0,0,0,3,0,0,0,3,0,0, - 0,115,19,0,0,0,116,0,0,131,0,0,106,1,0,124, - 1,0,116,2,0,131,2,0,83,40,1,0,0,0,117,81, - 0,0,0,85,115,101,32,116,104,101,32,100,101,102,97,117, - 108,116,32,112,97,116,104,32,104,111,111,107,32,119,104,101, - 110,32,78,111,110,101,32,105,115,32,115,116,111,114,101,100, - 32,105,110,10,32,32,32,32,32,32,32,32,115,121,115,46, - 112,97,116,104,95,105,109,112,111,114,116,101,114,95,99,97, - 99,104,101,46,40,3,0,0,0,117,5,0,0,0,115,117, - 112,101,114,117,20,0,0,0,95,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,117,18,0,0, - 0,95,68,69,70,65,85,76,84,95,80,65,84,72,95,72, - 79,79,75,40,2,0,0,0,117,3,0,0,0,99,108,115, - 117,4,0,0,0,112,97,116,104,40,1,0,0,0,117,10, - 0,0,0,64,95,95,99,108,97,115,115,95,95,40,0,0, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,12, + 0,0,0,95,102,105,110,100,95,109,111,100,117,108,101,163, + 3,0,0,115,16,0,0,0,0,2,13,1,13,1,18,1, + 12,2,15,1,4,2,21,2,117,12,0,0,0,95,102,105, + 110,100,95,109,111,100,117,108,101,99,3,0,0,0,0,0, + 0,0,4,0,0,0,4,0,0,0,67,0,0,0,115,194, + 0,0,0,116,0,0,124,0,0,116,1,0,131,2,0,115, + 45,0,116,2,0,100,1,0,106,3,0,116,4,0,124,0, + 0,131,1,0,131,1,0,131,1,0,130,1,0,110,0,0, + 124,2,0,100,2,0,107,0,0,114,72,0,116,5,0,100, + 3,0,131,1,0,130,1,0,110,0,0,124,1,0,114,156, + 0,116,0,0,124,1,0,116,1,0,131,2,0,115,108,0, + 116,2,0,100,4,0,131,1,0,130,1,0,113,156,0,124, + 1,0,116,6,0,106,7,0,107,7,0,114,156,0,100,5, + 0,125,3,0,116,8,0,124,3,0,106,3,0,124,1,0, + 131,1,0,131,1,0,130,1,0,113,156,0,110,0,0,124, + 0,0,12,114,190,0,124,2,0,100,2,0,107,2,0,114, + 190,0,116,5,0,100,6,0,131,1,0,130,1,0,110,0, + 0,100,7,0,83,40,8,0,0,0,117,28,0,0,0,86, + 101,114,105,102,121,32,97,114,103,117,109,101,110,116,115,32, + 97,114,101,32,34,115,97,110,101,34,46,117,31,0,0,0, + 109,111,100,117,108,101,32,110,97,109,101,32,109,117,115,116, + 32,98,101,32,115,116,114,44,32,110,111,116,32,123,125,105, + 0,0,0,0,117,18,0,0,0,108,101,118,101,108,32,109, + 117,115,116,32,98,101,32,62,61,32,48,117,31,0,0,0, + 95,95,112,97,99,107,97,103,101,95,95,32,110,111,116,32, + 115,101,116,32,116,111,32,97,32,115,116,114,105,110,103,117, + 62,0,0,0,80,97,114,101,110,116,32,109,111,100,117,108, + 101,32,123,48,33,114,125,32,110,111,116,32,108,111,97,100, + 101,100,44,32,99,97,110,110,111,116,32,112,101,114,102,111, + 114,109,32,114,101,108,97,116,105,118,101,32,105,109,112,111, + 114,116,117,17,0,0,0,69,109,112,116,121,32,109,111,100, + 117,108,101,32,110,97,109,101,78,40,9,0,0,0,117,10, + 0,0,0,105,115,105,110,115,116,97,110,99,101,117,3,0, + 0,0,115,116,114,117,9,0,0,0,84,121,112,101,69,114, + 114,111,114,117,6,0,0,0,102,111,114,109,97,116,117,4, + 0,0,0,116,121,112,101,117,10,0,0,0,86,97,108,117, + 101,69,114,114,111,114,117,3,0,0,0,115,121,115,117,7, + 0,0,0,109,111,100,117,108,101,115,117,11,0,0,0,83, + 121,115,116,101,109,69,114,114,111,114,40,4,0,0,0,117, + 4,0,0,0,110,97,109,101,117,7,0,0,0,112,97,99, + 107,97,103,101,117,5,0,0,0,108,101,118,101,108,117,3, + 0,0,0,109,115,103,40,0,0,0,0,40,0,0,0,0, + 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,62,117,13,0,0,0,95,115,97,110,105,116,121,95,99, + 104,101,99,107,178,3,0,0,115,24,0,0,0,0,2,15, + 1,30,1,12,1,15,1,6,1,15,1,15,1,15,1,6, + 2,27,1,19,1,117,13,0,0,0,95,115,97,110,105,116, + 121,95,99,104,101,99,107,117,20,0,0,0,78,111,32,109, + 111,100,117,108,101,32,110,97,109,101,100,32,123,33,114,125, + 99,2,0,0,0,0,0,0,0,8,0,0,0,20,0,0, + 0,67,0,0,0,115,207,1,0,0,100,9,0,125,2,0, + 124,0,0,106,1,0,100,1,0,131,1,0,100,2,0,25, + 125,3,0,124,3,0,114,175,0,124,3,0,116,2,0,106, + 3,0,107,7,0,114,59,0,124,1,0,124,3,0,131,1, + 0,1,110,0,0,124,0,0,116,2,0,106,3,0,107,6, + 0,114,85,0,116,2,0,106,3,0,124,0,0,25,83,116, + 2,0,106,3,0,124,3,0,25,125,4,0,121,13,0,124, + 4,0,106,4,0,125,2,0,87,113,175,0,4,116,5,0, + 107,10,0,114,171,0,1,1,1,116,6,0,100,3,0,23, + 106,7,0,124,0,0,124,3,0,131,2,0,125,5,0,116, + 8,0,124,5,0,100,4,0,124,0,0,131,1,1,130,1, + 0,89,113,175,0,88,110,0,0,116,9,0,124,0,0,124, + 2,0,131,2,0,125,6,0,124,6,0,100,9,0,107,8, + 0,114,232,0,116,8,0,116,6,0,106,7,0,124,0,0, + 131,1,0,100,4,0,124,0,0,131,1,1,130,1,0,110, + 62,0,124,0,0,116,2,0,106,3,0,107,6,0,114,7, + 1,116,2,0,106,3,0,124,0,0,25,125,7,0,110,31, + 0,124,6,0,106,10,0,124,0,0,131,1,0,125,7,0, + 116,11,0,100,5,0,124,0,0,124,6,0,131,3,0,1, + 124,3,0,114,89,1,116,2,0,106,3,0,124,3,0,25, + 125,4,0,116,12,0,124,4,0,124,0,0,106,1,0,100, + 1,0,131,1,0,100,6,0,25,124,7,0,131,3,0,1, + 110,0,0,116,13,0,124,7,0,100,7,0,131,2,0,12, + 115,120,1,124,7,0,106,14,0,100,9,0,107,8,0,114, + 203,1,121,59,0,124,7,0,106,15,0,124,7,0,95,14, + 0,116,13,0,124,7,0,100,8,0,131,2,0,115,178,1, + 124,7,0,106,14,0,106,1,0,100,1,0,131,1,0,100, + 2,0,25,124,7,0,95,14,0,110,0,0,87,113,203,1, + 4,116,5,0,107,10,0,114,199,1,1,1,1,89,113,203, + 1,88,110,0,0,124,7,0,83,40,10,0,0,0,117,25, + 0,0,0,70,105,110,100,32,97,110,100,32,108,111,97,100, + 32,116,104,101,32,109,111,100,117,108,101,46,117,1,0,0, + 0,46,105,0,0,0,0,117,21,0,0,0,59,32,123,125, + 32,105,115,32,110,111,116,32,97,32,112,97,99,107,97,103, + 101,117,4,0,0,0,110,97,109,101,117,18,0,0,0,105, + 109,112,111,114,116,32,123,33,114,125,32,35,32,123,33,114, + 125,105,2,0,0,0,117,11,0,0,0,95,95,112,97,99, + 107,97,103,101,95,95,117,8,0,0,0,95,95,112,97,116, + 104,95,95,78,40,16,0,0,0,117,4,0,0,0,78,111, + 110,101,117,10,0,0,0,114,112,97,114,116,105,116,105,111, + 110,117,3,0,0,0,115,121,115,117,7,0,0,0,109,111, + 100,117,108,101,115,117,8,0,0,0,95,95,112,97,116,104, + 95,95,117,14,0,0,0,65,116,116,114,105,98,117,116,101, + 69,114,114,111,114,117,8,0,0,0,95,69,82,82,95,77, + 83,71,117,6,0,0,0,102,111,114,109,97,116,117,11,0, + 0,0,73,109,112,111,114,116,69,114,114,111,114,117,12,0, + 0,0,95,102,105,110,100,95,109,111,100,117,108,101,117,11, + 0,0,0,108,111,97,100,95,109,111,100,117,108,101,117,15, + 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, + 103,101,117,7,0,0,0,115,101,116,97,116,116,114,117,7, + 0,0,0,104,97,115,97,116,116,114,117,11,0,0,0,95, + 95,112,97,99,107,97,103,101,95,95,117,8,0,0,0,95, + 95,110,97,109,101,95,95,40,8,0,0,0,117,4,0,0, + 0,110,97,109,101,117,7,0,0,0,105,109,112,111,114,116, + 95,117,4,0,0,0,112,97,116,104,117,6,0,0,0,112, + 97,114,101,110,116,117,13,0,0,0,112,97,114,101,110,116, + 95,109,111,100,117,108,101,117,3,0,0,0,109,115,103,117, + 6,0,0,0,108,111,97,100,101,114,117,6,0,0,0,109, + 111,100,117,108,101,40,0,0,0,0,40,0,0,0,0,117, + 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, + 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, + 62,117,14,0,0,0,95,102,105,110,100,95,97,110,100,95, + 108,111,97,100,199,3,0,0,115,62,0,0,0,0,2,6, + 1,19,1,6,1,15,1,13,2,15,1,11,2,13,1,3, + 1,13,1,13,1,22,1,26,1,15,1,12,1,30,1,15, + 2,16,2,15,1,16,1,6,2,13,1,32,2,31,1,3, + 1,12,1,15,1,32,1,13,1,8,1,117,14,0,0,0, + 95,102,105,110,100,95,97,110,100,95,108,111,97,100,105,0, + 0,0,0,99,3,0,0,0,0,0,0,0,5,0,0,0, + 18,0,0,0,67,0,0,0,115,172,0,0,0,116,0,0, + 124,0,0,124,1,0,124,2,0,131,3,0,1,124,2,0, + 100,1,0,107,4,0,114,49,0,116,1,0,124,0,0,124, + 1,0,124,2,0,131,3,0,125,0,0,110,0,0,116,2, + 0,131,0,0,143,108,0,1,121,69,0,116,3,0,106,4, + 0,124,0,0,25,125,3,0,124,3,0,100,4,0,107,8, + 0,114,123,0,100,2,0,106,6,0,124,0,0,131,1,0, + 125,4,0,116,7,0,124,4,0,100,3,0,124,0,0,131, + 1,1,130,1,0,110,0,0,124,3,0,83,87,110,18,0, + 4,116,8,0,107,10,0,114,148,0,1,1,1,89,110,1, + 0,88,116,9,0,124,0,0,116,10,0,131,2,0,83,87, + 100,4,0,81,88,100,4,0,83,40,5,0,0,0,117,50, + 1,0,0,73,109,112,111,114,116,32,97,110,100,32,114,101, + 116,117,114,110,32,116,104,101,32,109,111,100,117,108,101,32, + 98,97,115,101,100,32,111,110,32,105,116,115,32,110,97,109, + 101,44,32,116,104,101,32,112,97,99,107,97,103,101,32,116, + 104,101,32,99,97,108,108,32,105,115,10,32,32,32,32,98, + 101,105,110,103,32,109,97,100,101,32,102,114,111,109,44,32, + 97,110,100,32,116,104,101,32,108,101,118,101,108,32,97,100, + 106,117,115,116,109,101,110,116,46,10,10,32,32,32,32,84, + 104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,112, + 114,101,115,101,110,116,115,32,116,104,101,32,103,114,101,97, + 116,101,115,116,32,99,111,109,109,111,110,32,100,101,110,111, + 109,105,110,97,116,111,114,32,111,102,32,102,117,110,99,116, + 105,111,110,97,108,105,116,121,10,32,32,32,32,98,101,116, + 119,101,101,110,32,105,109,112,111,114,116,95,109,111,100,117, + 108,101,32,97,110,100,32,95,95,105,109,112,111,114,116,95, + 95,46,32,84,104,105,115,32,105,110,99,108,117,100,101,115, + 32,115,101,116,116,105,110,103,32,95,95,112,97,99,107,97, + 103,101,95,95,32,105,102,10,32,32,32,32,116,104,101,32, + 108,111,97,100,101,114,32,100,105,100,32,110,111,116,46,10, + 10,32,32,32,32,105,0,0,0,0,117,40,0,0,0,105, + 109,112,111,114,116,32,111,102,32,123,125,32,104,97,108,116, + 101,100,59,32,78,111,110,101,32,105,110,32,115,121,115,46, + 109,111,100,117,108,101,115,117,4,0,0,0,110,97,109,101, + 78,40,11,0,0,0,117,13,0,0,0,95,115,97,110,105, + 116,121,95,99,104,101,99,107,117,13,0,0,0,95,114,101, + 115,111,108,118,101,95,110,97,109,101,117,18,0,0,0,95, + 73,109,112,111,114,116,76,111,99,107,67,111,110,116,101,120, + 116,117,3,0,0,0,115,121,115,117,7,0,0,0,109,111, + 100,117,108,101,115,117,4,0,0,0,78,111,110,101,117,6, + 0,0,0,102,111,114,109,97,116,117,11,0,0,0,73,109, + 112,111,114,116,69,114,114,111,114,117,8,0,0,0,75,101, + 121,69,114,114,111,114,117,14,0,0,0,95,102,105,110,100, + 95,97,110,100,95,108,111,97,100,117,11,0,0,0,95,103, + 99,100,95,105,109,112,111,114,116,40,5,0,0,0,117,4, + 0,0,0,110,97,109,101,117,7,0,0,0,112,97,99,107, + 97,103,101,117,5,0,0,0,108,101,118,101,108,117,6,0, + 0,0,109,111,100,117,108,101,117,7,0,0,0,109,101,115, + 115,97,103,101,40,0,0,0,0,40,0,0,0,0,117,29, + 0,0,0,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,62, + 117,11,0,0,0,95,103,99,100,95,105,109,112,111,114,116, + 240,3,0,0,115,28,0,0,0,0,9,16,1,12,1,21, + 1,10,1,3,1,13,1,12,1,6,1,9,1,21,1,8, + 1,13,1,5,1,117,11,0,0,0,95,103,99,100,95,105, + 109,112,111,114,116,99,3,0,0,0,0,0,0,0,4,0, + 0,0,13,0,0,0,3,0,0,0,115,179,0,0,0,116, + 0,0,136,0,0,100,1,0,131,2,0,114,175,0,100,2, + 0,124,1,0,107,6,0,114,86,0,116,0,0,136,0,0, + 100,3,0,131,2,0,114,86,0,116,1,0,124,1,0,131, + 1,0,125,1,0,124,1,0,106,2,0,100,2,0,131,1, + 0,1,124,1,0,106,3,0,136,0,0,106,4,0,131,1, + 0,1,110,0,0,120,86,0,135,0,0,102,1,0,100,4, + 0,100,5,0,134,0,0,124,1,0,68,131,1,0,68,93, + 56,0,125,3,0,121,29,0,124,2,0,100,6,0,106,5, + 0,136,0,0,106,6,0,124,3,0,131,2,0,131,1,0, + 1,87,113,112,0,4,116,7,0,107,10,0,114,167,0,1, + 1,1,89,113,112,0,88,113,112,0,87,110,0,0,136,0, + 0,83,40,7,0,0,0,117,238,0,0,0,70,105,103,117, + 114,101,32,111,117,116,32,119,104,97,116,32,95,95,105,109, + 112,111,114,116,95,95,32,115,104,111,117,108,100,32,114,101, + 116,117,114,110,46,10,10,32,32,32,32,84,104,101,32,105, + 109,112,111,114,116,95,32,112,97,114,97,109,101,116,101,114, + 32,105,115,32,97,32,99,97,108,108,97,98,108,101,32,119, + 104,105,99,104,32,116,97,107,101,115,32,116,104,101,32,110, + 97,109,101,32,111,102,32,109,111,100,117,108,101,32,116,111, + 10,32,32,32,32,105,109,112,111,114,116,46,32,73,116,32, + 105,115,32,114,101,113,117,105,114,101,100,32,116,111,32,100, + 101,99,111,117,112,108,101,32,116,104,101,32,102,117,110,99, + 116,105,111,110,32,102,114,111,109,32,97,115,115,117,109,105, + 110,103,32,105,109,112,111,114,116,108,105,98,39,115,10,32, + 32,32,32,105,109,112,111,114,116,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,105,115,32,100,101,115,105, + 114,101,100,46,10,10,32,32,32,32,117,8,0,0,0,95, + 95,112,97,116,104,95,95,117,1,0,0,0,42,117,7,0, + 0,0,95,95,97,108,108,95,95,99,1,0,0,0,0,0, + 0,0,2,0,0,0,4,0,0,0,51,0,0,0,115,36, + 0,0,0,124,0,0,93,26,0,125,1,0,116,0,0,136, + 0,0,124,1,0,131,2,0,115,3,0,124,1,0,86,1, + 113,3,0,100,0,0,83,40,1,0,0,0,78,40,1,0, + 0,0,117,7,0,0,0,104,97,115,97,116,116,114,40,2, + 0,0,0,117,2,0,0,0,46,48,117,1,0,0,0,121, + 40,1,0,0,0,117,6,0,0,0,109,111,100,117,108,101, + 40,0,0,0,0,117,29,0,0,0,60,102,114,111,122,101, + 110,32,105,109,112,111,114,116,108,105,98,46,95,98,111,111, + 116,115,116,114,97,112,62,117,9,0,0,0,60,103,101,110, + 101,120,112,114,62,24,4,0,0,115,2,0,0,0,6,0, + 117,35,0,0,0,95,104,97,110,100,108,101,95,102,114,111, + 109,108,105,115,116,46,60,108,111,99,97,108,115,62,46,60, + 103,101,110,101,120,112,114,62,117,7,0,0,0,123,48,125, + 46,123,49,125,40,8,0,0,0,117,7,0,0,0,104,97, + 115,97,116,116,114,117,4,0,0,0,108,105,115,116,117,6, + 0,0,0,114,101,109,111,118,101,117,6,0,0,0,101,120, + 116,101,110,100,117,7,0,0,0,95,95,97,108,108,95,95, + 117,6,0,0,0,102,111,114,109,97,116,117,8,0,0,0, + 95,95,110,97,109,101,95,95,117,11,0,0,0,73,109,112, + 111,114,116,69,114,114,111,114,40,4,0,0,0,117,6,0, + 0,0,109,111,100,117,108,101,117,8,0,0,0,102,114,111, + 109,108,105,115,116,117,7,0,0,0,105,109,112,111,114,116, + 95,117,1,0,0,0,120,40,0,0,0,0,40,1,0,0, + 0,117,6,0,0,0,109,111,100,117,108,101,117,29,0,0, + 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,16, + 0,0,0,95,104,97,110,100,108,101,95,102,114,111,109,108, + 105,115,116,9,4,0,0,115,22,0,0,0,0,10,15,1, + 27,1,12,1,13,1,19,1,32,1,3,1,29,1,13,1, + 12,1,117,16,0,0,0,95,104,97,110,100,108,101,95,102, + 114,111,109,108,105,115,116,99,1,0,0,0,0,0,0,0, + 2,0,0,0,2,0,0,0,67,0,0,0,115,78,0,0, + 0,124,0,0,106,0,0,100,1,0,131,1,0,125,1,0, + 124,1,0,100,6,0,107,8,0,114,74,0,124,0,0,100, + 2,0,25,125,1,0,100,3,0,124,0,0,107,7,0,114, + 74,0,124,1,0,106,2,0,100,4,0,131,1,0,100,5, + 0,25,125,1,0,113,74,0,110,0,0,124,1,0,83,40, + 7,0,0,0,117,167,0,0,0,67,97,108,99,117,108,97, + 116,101,32,119,104,97,116,32,95,95,112,97,99,107,97,103, + 101,95,95,32,115,104,111,117,108,100,32,98,101,46,10,10, + 32,32,32,32,95,95,112,97,99,107,97,103,101,95,95,32, + 105,115,32,110,111,116,32,103,117,97,114,97,110,116,101,101, + 100,32,116,111,32,98,101,32,100,101,102,105,110,101,100,32, + 111,114,32,99,111,117,108,100,32,98,101,32,115,101,116,32, + 116,111,32,78,111,110,101,10,32,32,32,32,116,111,32,114, + 101,112,114,101,115,101,110,116,32,116,104,97,116,32,105,116, + 115,32,112,114,111,112,101,114,32,118,97,108,117,101,32,105, + 115,32,117,110,107,110,111,119,110,46,10,10,32,32,32,32, + 117,11,0,0,0,95,95,112,97,99,107,97,103,101,95,95, + 117,8,0,0,0,95,95,110,97,109,101,95,95,117,8,0, + 0,0,95,95,112,97,116,104,95,95,117,1,0,0,0,46, + 105,0,0,0,0,78,40,3,0,0,0,117,3,0,0,0, + 103,101,116,117,4,0,0,0,78,111,110,101,117,10,0,0, + 0,114,112,97,114,116,105,116,105,111,110,40,2,0,0,0, + 117,7,0,0,0,103,108,111,98,97,108,115,117,7,0,0, + 0,112,97,99,107,97,103,101,40,0,0,0,0,40,0,0, 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,20,0,0,0,95,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,134,3,0, - 0,115,2,0,0,0,0,4,117,39,0,0,0,95,68,101, - 102,97,117,108,116,80,97,116,104,70,105,110,100,101,114,46, - 95,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, - 97,99,104,101,40,7,0,0,0,117,8,0,0,0,95,95, - 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, - 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, - 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, - 95,95,117,11,0,0,0,99,108,97,115,115,109,101,116,104, - 111,100,117,11,0,0,0,95,112,97,116,104,95,104,111,111, - 107,115,117,20,0,0,0,95,112,97,116,104,95,105,109,112, - 111,114,116,101,114,95,99,97,99,104,101,40,1,0,0,0, - 117,10,0,0,0,95,95,108,111,99,97,108,115,95,95,40, - 0,0,0,0,40,1,0,0,0,117,10,0,0,0,64,95, - 95,99,108,97,115,115,95,95,117,29,0,0,0,60,102,114, - 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, - 98,111,111,116,115,116,114,97,112,62,117,18,0,0,0,95, - 68,101,102,97,117,108,116,80,97,116,104,70,105,110,100,101, - 114,120,3,0,0,115,6,0,0,0,16,3,6,2,24,9, - 117,18,0,0,0,95,68,101,102,97,117,108,116,80,97,116, - 104,70,105,110,100,101,114,99,1,0,0,0,0,0,0,0, - 1,0,0,0,2,0,0,0,66,0,0,0,115,50,0,0, - 0,124,0,0,69,101,0,0,90,1,0,100,0,0,90,2, - 0,100,1,0,90,3,0,100,2,0,100,3,0,132,0,0, - 90,4,0,100,4,0,100,5,0,132,0,0,90,5,0,100, - 6,0,83,40,7,0,0,0,117,18,0,0,0,95,73,109, - 112,111,114,116,76,111,99,107,67,111,110,116,101,120,116,117, - 36,0,0,0,67,111,110,116,101,120,116,32,109,97,110,97, - 103,101,114,32,102,111,114,32,116,104,101,32,105,109,112,111, - 114,116,32,108,111,99,107,46,99,1,0,0,0,0,0,0, - 0,1,0,0,0,1,0,0,0,67,0,0,0,115,14,0, - 0,0,116,0,0,106,1,0,131,0,0,1,100,1,0,83, - 40,2,0,0,0,117,24,0,0,0,65,99,113,117,105,114, - 101,32,116,104,101,32,105,109,112,111,114,116,32,108,111,99, - 107,46,78,40,2,0,0,0,117,4,0,0,0,95,105,109, - 112,117,12,0,0,0,97,99,113,117,105,114,101,95,108,111, - 99,107,40,1,0,0,0,117,4,0,0,0,115,101,108,102, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,9,0,0, - 0,95,95,101,110,116,101,114,95,95,145,3,0,0,115,2, - 0,0,0,0,2,117,28,0,0,0,95,73,109,112,111,114, - 116,76,111,99,107,67,111,110,116,101,120,116,46,95,95,101, - 110,116,101,114,95,95,99,4,0,0,0,0,0,0,0,4, - 0,0,0,1,0,0,0,67,0,0,0,115,14,0,0,0, - 116,0,0,106,1,0,131,0,0,1,100,1,0,83,40,2, - 0,0,0,117,60,0,0,0,82,101,108,101,97,115,101,32, - 116,104,101,32,105,109,112,111,114,116,32,108,111,99,107,32, - 114,101,103,97,114,100,108,101,115,115,32,111,102,32,97,110, - 121,32,114,97,105,115,101,100,32,101,120,99,101,112,116,105, - 111,110,115,46,78,40,2,0,0,0,117,4,0,0,0,95, - 105,109,112,117,12,0,0,0,114,101,108,101,97,115,101,95, - 108,111,99,107,40,4,0,0,0,117,4,0,0,0,115,101, - 108,102,117,8,0,0,0,101,120,99,95,116,121,112,101,117, - 9,0,0,0,101,120,99,95,118,97,108,117,101,117,13,0, - 0,0,101,120,99,95,116,114,97,99,101,98,97,99,107,40, - 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,8,0,0,0, - 95,95,101,120,105,116,95,95,149,3,0,0,115,2,0,0, - 0,0,2,117,27,0,0,0,95,73,109,112,111,114,116,76, - 111,99,107,67,111,110,116,101,120,116,46,95,95,101,120,105, - 116,95,95,78,40,6,0,0,0,117,8,0,0,0,95,95, - 110,97,109,101,95,95,117,10,0,0,0,95,95,109,111,100, - 117,108,101,95,95,117,12,0,0,0,95,95,113,117,97,108, - 110,97,109,101,95,95,117,7,0,0,0,95,95,100,111,99, - 95,95,117,9,0,0,0,95,95,101,110,116,101,114,95,95, - 117,8,0,0,0,95,95,101,120,105,116,95,95,40,1,0, - 0,0,117,10,0,0,0,95,95,108,111,99,97,108,115,95, - 95,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,18,0, - 0,0,95,73,109,112,111,114,116,76,111,99,107,67,111,110, - 116,101,120,116,141,3,0,0,115,6,0,0,0,16,2,6, - 2,12,4,117,18,0,0,0,95,73,109,112,111,114,116,76, - 111,99,107,67,111,110,116,101,120,116,99,3,0,0,0,0, - 0,0,0,5,0,0,0,4,0,0,0,67,0,0,0,115, - 91,0,0,0,124,1,0,106,0,0,100,1,0,124,2,0, - 100,2,0,24,131,2,0,125,3,0,116,1,0,124,3,0, - 131,1,0,124,2,0,107,0,0,114,55,0,116,2,0,100, - 3,0,131,1,0,130,1,0,110,0,0,124,3,0,100,4, - 0,25,125,4,0,124,0,0,114,87,0,100,5,0,106,3, - 0,124,4,0,124,0,0,131,2,0,83,124,4,0,83,40, - 6,0,0,0,117,50,0,0,0,82,101,115,111,108,118,101, - 32,97,32,114,101,108,97,116,105,118,101,32,109,111,100,117, - 108,101,32,110,97,109,101,32,116,111,32,97,110,32,97,98, - 115,111,108,117,116,101,32,111,110,101,46,117,1,0,0,0, - 46,105,1,0,0,0,117,50,0,0,0,97,116,116,101,109, - 112,116,101,100,32,114,101,108,97,116,105,118,101,32,105,109, - 112,111,114,116,32,98,101,121,111,110,100,32,116,111,112,45, - 108,101,118,101,108,32,112,97,99,107,97,103,101,105,0,0, - 0,0,117,7,0,0,0,123,48,125,46,123,49,125,40,4, - 0,0,0,117,6,0,0,0,114,115,112,108,105,116,117,3, - 0,0,0,108,101,110,117,10,0,0,0,86,97,108,117,101, - 69,114,114,111,114,117,6,0,0,0,102,111,114,109,97,116, - 40,5,0,0,0,117,4,0,0,0,110,97,109,101,117,7, - 0,0,0,112,97,99,107,97,103,101,117,5,0,0,0,108, - 101,118,101,108,117,4,0,0,0,98,105,116,115,117,4,0, - 0,0,98,97,115,101,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,13,0,0,0,95,114,101,115,111,108,118,101,95, - 110,97,109,101,154,3,0,0,115,10,0,0,0,0,2,22, - 1,18,1,15,1,10,1,117,13,0,0,0,95,114,101,115, - 111,108,118,101,95,110,97,109,101,99,2,0,0,0,0,0, - 0,0,5,0,0,0,4,0,0,0,67,0,0,0,115,104, - 0,0,0,116,0,0,106,1,0,116,2,0,23,125,2,0, - 120,84,0,124,2,0,68,93,72,0,125,3,0,124,3,0, - 106,3,0,124,0,0,124,1,0,131,2,0,125,4,0,124, - 4,0,100,1,0,107,9,0,114,20,0,124,0,0,116,0, - 0,106,5,0,107,7,0,114,75,0,124,4,0,83,116,0, - 0,106,5,0,124,0,0,25,106,6,0,83,113,20,0,113, - 20,0,87,100,1,0,83,100,1,0,83,40,2,0,0,0, - 117,23,0,0,0,70,105,110,100,32,97,32,109,111,100,117, - 108,101,39,115,32,108,111,97,100,101,114,46,78,40,7,0, - 0,0,117,3,0,0,0,115,121,115,117,9,0,0,0,109, - 101,116,97,95,112,97,116,104,117,19,0,0,0,95,73,77, - 80,76,73,67,73,84,95,77,69,84,65,95,80,65,84,72, - 117,11,0,0,0,102,105,110,100,95,109,111,100,117,108,101, - 117,4,0,0,0,78,111,110,101,117,7,0,0,0,109,111, - 100,117,108,101,115,117,10,0,0,0,95,95,108,111,97,100, - 101,114,95,95,40,5,0,0,0,117,4,0,0,0,110,97, - 109,101,117,4,0,0,0,112,97,116,104,117,9,0,0,0, - 109,101,116,97,95,112,97,116,104,117,6,0,0,0,102,105, - 110,100,101,114,117,6,0,0,0,108,111,97,100,101,114,40, - 0,0,0,0,40,0,0,0,0,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,12,0,0,0, - 95,102,105,110,100,95,109,111,100,117,108,101,163,3,0,0, - 115,16,0,0,0,0,2,13,1,13,1,18,1,12,2,15, - 1,4,2,21,2,117,12,0,0,0,95,102,105,110,100,95, - 109,111,100,117,108,101,99,3,0,0,0,0,0,0,0,4, - 0,0,0,4,0,0,0,67,0,0,0,115,194,0,0,0, - 116,0,0,124,0,0,116,1,0,131,2,0,115,45,0,116, - 2,0,100,1,0,106,3,0,116,4,0,124,0,0,131,1, - 0,131,1,0,131,1,0,130,1,0,110,0,0,124,2,0, - 100,2,0,107,0,0,114,72,0,116,5,0,100,3,0,131, - 1,0,130,1,0,110,0,0,124,1,0,114,156,0,116,0, - 0,124,1,0,116,1,0,131,2,0,115,108,0,116,2,0, - 100,4,0,131,1,0,130,1,0,113,156,0,124,1,0,116, - 6,0,106,7,0,107,7,0,114,156,0,100,5,0,125,3, - 0,116,8,0,124,3,0,106,3,0,124,1,0,131,1,0, - 131,1,0,130,1,0,113,156,0,110,0,0,124,0,0,12, - 114,190,0,124,2,0,100,2,0,107,2,0,114,190,0,116, - 5,0,100,6,0,131,1,0,130,1,0,110,0,0,100,7, - 0,83,40,8,0,0,0,117,28,0,0,0,86,101,114,105, - 102,121,32,97,114,103,117,109,101,110,116,115,32,97,114,101, - 32,34,115,97,110,101,34,46,117,31,0,0,0,109,111,100, - 117,108,101,32,110,97,109,101,32,109,117,115,116,32,98,101, - 32,115,116,114,44,32,110,111,116,32,123,125,105,0,0,0, - 0,117,18,0,0,0,108,101,118,101,108,32,109,117,115,116, - 32,98,101,32,62,61,32,48,117,31,0,0,0,95,95,112, - 97,99,107,97,103,101,95,95,32,110,111,116,32,115,101,116, - 32,116,111,32,97,32,115,116,114,105,110,103,117,62,0,0, - 0,80,97,114,101,110,116,32,109,111,100,117,108,101,32,123, - 48,33,114,125,32,110,111,116,32,108,111,97,100,101,100,44, - 32,99,97,110,110,111,116,32,112,101,114,102,111,114,109,32, - 114,101,108,97,116,105,118,101,32,105,109,112,111,114,116,117, - 17,0,0,0,69,109,112,116,121,32,109,111,100,117,108,101, - 32,110,97,109,101,78,40,9,0,0,0,117,10,0,0,0, - 105,115,105,110,115,116,97,110,99,101,117,3,0,0,0,115, - 116,114,117,9,0,0,0,84,121,112,101,69,114,114,111,114, - 117,6,0,0,0,102,111,114,109,97,116,117,4,0,0,0, - 116,121,112,101,117,10,0,0,0,86,97,108,117,101,69,114, - 114,111,114,117,3,0,0,0,115,121,115,117,7,0,0,0, - 109,111,100,117,108,101,115,117,11,0,0,0,83,121,115,116, - 101,109,69,114,114,111,114,40,4,0,0,0,117,4,0,0, - 0,110,97,109,101,117,7,0,0,0,112,97,99,107,97,103, - 101,117,5,0,0,0,108,101,118,101,108,117,3,0,0,0, - 109,115,103,40,0,0,0,0,40,0,0,0,0,117,29,0, + 114,97,112,62,117,17,0,0,0,95,99,97,108,99,95,95, + 95,112,97,99,107,97,103,101,95,95,32,4,0,0,115,12, + 0,0,0,0,7,15,1,12,1,10,1,12,1,25,1,117, + 17,0,0,0,95,99,97,108,99,95,95,95,112,97,99,107, + 97,103,101,95,95,99,5,0,0,0,0,0,0,0,9,0, + 0,0,5,0,0,0,67,0,0,0,115,235,0,0,0,124, + 4,0,100,1,0,107,2,0,114,27,0,116,0,0,124,0, + 0,131,1,0,125,5,0,110,30,0,116,1,0,124,1,0, + 131,1,0,125,6,0,116,0,0,124,0,0,124,6,0,124, + 4,0,131,3,0,125,5,0,124,3,0,115,215,0,124,4, + 0,100,1,0,107,2,0,114,130,0,124,0,0,106,2,0, + 100,2,0,131,1,0,125,7,0,124,7,0,100,5,0,107, + 2,0,114,106,0,124,5,0,83,116,3,0,106,4,0,124, + 0,0,100,4,0,124,7,0,133,2,0,25,25,83,113,231, + 0,124,0,0,115,140,0,124,5,0,83,116,5,0,124,0, + 0,131,1,0,116,5,0,124,0,0,106,6,0,100,2,0, + 131,1,0,100,1,0,25,131,1,0,24,125,8,0,116,3, + 0,106,4,0,124,5,0,106,7,0,100,4,0,116,5,0, + 124,5,0,106,7,0,131,1,0,124,8,0,24,133,2,0, + 25,25,83,110,16,0,116,8,0,124,5,0,124,3,0,116, + 0,0,131,3,0,83,100,4,0,83,40,6,0,0,0,117, + 214,1,0,0,73,109,112,111,114,116,32,97,32,109,111,100, + 117,108,101,46,10,10,32,32,32,32,84,104,101,32,39,103, + 108,111,98,97,108,115,39,32,97,114,103,117,109,101,110,116, + 32,105,115,32,117,115,101,100,32,116,111,32,105,110,102,101, + 114,32,119,104,101,114,101,32,116,104,101,32,105,109,112,111, + 114,116,32,105,115,32,111,99,99,117,114,105,110,103,32,102, + 114,111,109,10,32,32,32,32,116,111,32,104,97,110,100,108, + 101,32,114,101,108,97,116,105,118,101,32,105,109,112,111,114, + 116,115,46,32,84,104,101,32,39,108,111,99,97,108,115,39, + 32,97,114,103,117,109,101,110,116,32,105,115,32,105,103,110, + 111,114,101,100,46,32,84,104,101,10,32,32,32,32,39,102, + 114,111,109,108,105,115,116,39,32,97,114,103,117,109,101,110, + 116,32,115,112,101,99,105,102,105,101,115,32,119,104,97,116, + 32,115,104,111,117,108,100,32,101,120,105,115,116,32,97,115, + 32,97,116,116,114,105,98,117,116,101,115,32,111,110,32,116, + 104,101,32,109,111,100,117,108,101,10,32,32,32,32,98,101, + 105,110,103,32,105,109,112,111,114,116,101,100,32,40,101,46, + 103,46,32,96,96,102,114,111,109,32,109,111,100,117,108,101, + 32,105,109,112,111,114,116,32,60,102,114,111,109,108,105,115, + 116,62,96,96,41,46,32,32,84,104,101,32,39,108,101,118, + 101,108,39,10,32,32,32,32,97,114,103,117,109,101,110,116, + 32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32, + 112,97,99,107,97,103,101,32,108,111,99,97,116,105,111,110, + 32,116,111,32,105,109,112,111,114,116,32,102,114,111,109,32, + 105,110,32,97,32,114,101,108,97,116,105,118,101,10,32,32, + 32,32,105,109,112,111,114,116,32,40,101,46,103,46,32,96, + 96,102,114,111,109,32,46,46,112,107,103,32,105,109,112,111, + 114,116,32,109,111,100,96,96,32,119,111,117,108,100,32,104, + 97,118,101,32,97,32,39,108,101,118,101,108,39,32,111,102, + 32,50,41,46,10,10,32,32,32,32,105,0,0,0,0,117, + 1,0,0,0,46,105,1,0,0,0,78,105,255,255,255,255, + 40,9,0,0,0,117,11,0,0,0,95,103,99,100,95,105, + 109,112,111,114,116,117,17,0,0,0,95,99,97,108,99,95, + 95,95,112,97,99,107,97,103,101,95,95,117,4,0,0,0, + 102,105,110,100,117,3,0,0,0,115,121,115,117,7,0,0, + 0,109,111,100,117,108,101,115,117,3,0,0,0,108,101,110, + 117,9,0,0,0,112,97,114,116,105,116,105,111,110,117,8, + 0,0,0,95,95,110,97,109,101,95,95,117,16,0,0,0, + 95,104,97,110,100,108,101,95,102,114,111,109,108,105,115,116, + 40,9,0,0,0,117,4,0,0,0,110,97,109,101,117,7, + 0,0,0,103,108,111,98,97,108,115,117,6,0,0,0,108, + 111,99,97,108,115,117,8,0,0,0,102,114,111,109,108,105, + 115,116,117,5,0,0,0,108,101,118,101,108,117,6,0,0, + 0,109,111,100,117,108,101,117,7,0,0,0,112,97,99,107, + 97,103,101,117,5,0,0,0,105,110,100,101,120,117,7,0, + 0,0,99,117,116,95,111,102,102,40,0,0,0,0,40,0, + 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, + 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, + 116,114,97,112,62,117,10,0,0,0,95,95,105,109,112,111, + 114,116,95,95,47,4,0,0,115,30,0,0,0,0,11,12, + 1,15,2,12,1,18,1,6,3,12,1,15,1,12,1,4, + 2,24,1,6,1,4,2,35,1,40,2,117,10,0,0,0, + 95,95,105,109,112,111,114,116,95,95,99,2,0,0,0,0, + 0,0,0,9,0,0,0,12,0,0,0,67,0,0,0,115, + 109,1,0,0,124,1,0,97,0,0,124,0,0,97,1,0, + 120,47,0,116,0,0,116,1,0,102,2,0,68,93,33,0, + 125,2,0,116,2,0,124,2,0,100,1,0,131,2,0,115, + 25,0,116,3,0,124,2,0,95,4,0,113,25,0,113,25, + 0,87,116,1,0,106,5,0,116,6,0,25,125,3,0,120, + 76,0,100,17,0,68,93,68,0,125,4,0,124,4,0,116, + 1,0,106,5,0,107,7,0,114,121,0,116,3,0,106,7, + 0,124,4,0,131,1,0,125,5,0,110,13,0,116,1,0, + 106,5,0,124,4,0,25,125,5,0,116,8,0,124,3,0, + 124,4,0,124,5,0,131,3,0,1,113,82,0,87,120,153, + 0,100,18,0,100,19,0,100,20,0,103,3,0,68,93,124, + 0,92,2,0,125,6,0,125,7,0,124,6,0,116,1,0, + 106,5,0,107,6,0,114,214,0,116,1,0,106,5,0,124, + 6,0,25,125,8,0,80,113,170,0,121,56,0,116,3,0, + 106,7,0,124,6,0,131,1,0,125,8,0,124,6,0,100, + 10,0,107,2,0,114,12,1,100,11,0,116,1,0,106,9, + 0,107,6,0,114,12,1,100,7,0,125,7,0,110,0,0, + 80,87,113,170,0,4,116,10,0,107,10,0,114,37,1,1, + 1,1,119,170,0,89,113,170,0,88,113,170,0,87,116,10, + 0,100,12,0,131,1,0,130,1,0,116,8,0,124,3,0, + 100,13,0,124,8,0,131,3,0,1,116,8,0,124,3,0, + 100,14,0,124,7,0,131,3,0,1,116,8,0,124,3,0, + 100,15,0,116,11,0,131,0,0,131,3,0,1,100,16,0, + 83,40,21,0,0,0,117,250,0,0,0,83,101,116,117,112, + 32,105,109,112,111,114,116,108,105,98,32,98,121,32,105,109, + 112,111,114,116,105,110,103,32,110,101,101,100,101,100,32,98, + 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,32, + 97,110,100,32,105,110,106,101,99,116,105,110,103,32,116,104, + 101,109,10,32,32,32,32,105,110,116,111,32,116,104,101,32, + 103,108,111,98,97,108,32,110,97,109,101,115,112,97,99,101, + 46,10,10,32,32,32,32,65,115,32,115,121,115,32,105,115, + 32,110,101,101,100,101,100,32,102,111,114,32,115,121,115,46, + 109,111,100,117,108,101,115,32,97,99,99,101,115,115,32,97, + 110,100,32,95,105,109,112,32,105,115,32,110,101,101,100,101, + 100,32,116,111,32,108,111,97,100,32,98,117,105,108,116,45, + 105,110,10,32,32,32,32,109,111,100,117,108,101,115,44,32, + 116,104,111,115,101,32,116,119,111,32,109,111,100,117,108,101, + 115,32,109,117,115,116,32,98,101,32,101,120,112,108,105,99, + 105,116,108,121,32,112,97,115,115,101,100,32,105,110,46,10, + 10,32,32,32,32,117,10,0,0,0,95,95,108,111,97,100, + 101,114,95,95,117,3,0,0,0,95,105,111,117,9,0,0, + 0,95,119,97,114,110,105,110,103,115,117,8,0,0,0,98, + 117,105,108,116,105,110,115,117,7,0,0,0,109,97,114,115, + 104,97,108,117,5,0,0,0,112,111,115,105,120,117,1,0, + 0,0,47,117,2,0,0,0,110,116,117,1,0,0,0,92, + 117,3,0,0,0,111,115,50,117,7,0,0,0,69,77,88, + 32,71,67,67,117,30,0,0,0,105,109,112,111,114,116,108, + 105,98,32,114,101,113,117,105,114,101,115,32,112,111,115,105, + 120,32,111,114,32,110,116,117,3,0,0,0,95,111,115,117, + 8,0,0,0,112,97,116,104,95,115,101,112,117,11,0,0, + 0,95,114,101,108,97,120,95,99,97,115,101,78,40,4,0, + 0,0,117,3,0,0,0,95,105,111,117,9,0,0,0,95, + 119,97,114,110,105,110,103,115,117,8,0,0,0,98,117,105, + 108,116,105,110,115,117,7,0,0,0,109,97,114,115,104,97, + 108,40,2,0,0,0,117,5,0,0,0,112,111,115,105,120, + 117,1,0,0,0,47,40,2,0,0,0,117,2,0,0,0, + 110,116,117,1,0,0,0,92,40,2,0,0,0,117,3,0, + 0,0,111,115,50,117,1,0,0,0,92,40,12,0,0,0, + 117,4,0,0,0,95,105,109,112,117,3,0,0,0,115,121, + 115,117,7,0,0,0,104,97,115,97,116,116,114,117,15,0, + 0,0,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 114,117,10,0,0,0,95,95,108,111,97,100,101,114,95,95, + 117,7,0,0,0,109,111,100,117,108,101,115,117,8,0,0, + 0,95,95,110,97,109,101,95,95,117,11,0,0,0,108,111, + 97,100,95,109,111,100,117,108,101,117,7,0,0,0,115,101, + 116,97,116,116,114,117,7,0,0,0,118,101,114,115,105,111, + 110,117,11,0,0,0,73,109,112,111,114,116,69,114,114,111, + 114,117,16,0,0,0,95,109,97,107,101,95,114,101,108,97, + 120,95,99,97,115,101,40,9,0,0,0,117,10,0,0,0, + 115,121,115,95,109,111,100,117,108,101,117,11,0,0,0,95, + 105,109,112,95,109,111,100,117,108,101,117,6,0,0,0,109, + 111,100,117,108,101,117,11,0,0,0,115,101,108,102,95,109, + 111,100,117,108,101,117,12,0,0,0,98,117,105,108,116,105, + 110,95,110,97,109,101,117,14,0,0,0,98,117,105,108,116, + 105,110,95,109,111,100,117,108,101,117,10,0,0,0,98,117, + 105,108,116,105,110,95,111,115,117,8,0,0,0,112,97,116, + 104,95,115,101,112,117,9,0,0,0,111,115,95,109,111,100, + 117,108,101,40,0,0,0,0,40,0,0,0,0,117,29,0, 0,0,60,102,114,111,122,101,110,32,105,109,112,111,114,116, 108,105,98,46,95,98,111,111,116,115,116,114,97,112,62,117, - 13,0,0,0,95,115,97,110,105,116,121,95,99,104,101,99, - 107,178,3,0,0,115,24,0,0,0,0,2,15,1,30,1, - 12,1,15,1,6,1,15,1,15,1,15,1,6,2,27,1, - 19,1,117,13,0,0,0,95,115,97,110,105,116,121,95,99, - 104,101,99,107,117,20,0,0,0,78,111,32,109,111,100,117, - 108,101,32,110,97,109,101,100,32,123,33,114,125,99,2,0, - 0,0,0,0,0,0,8,0,0,0,20,0,0,0,67,0, - 0,0,115,207,1,0,0,100,9,0,125,2,0,124,0,0, - 106,1,0,100,1,0,131,1,0,100,2,0,25,125,3,0, - 124,3,0,114,175,0,124,3,0,116,2,0,106,3,0,107, - 7,0,114,59,0,124,1,0,124,3,0,131,1,0,1,110, - 0,0,124,0,0,116,2,0,106,3,0,107,6,0,114,85, - 0,116,2,0,106,3,0,124,0,0,25,83,116,2,0,106, - 3,0,124,3,0,25,125,4,0,121,13,0,124,4,0,106, - 4,0,125,2,0,87,113,175,0,4,116,5,0,107,10,0, - 114,171,0,1,1,1,116,6,0,100,3,0,23,106,7,0, - 124,0,0,124,3,0,131,2,0,125,5,0,116,8,0,124, - 5,0,100,4,0,124,0,0,131,1,1,130,1,0,89,113, - 175,0,88,110,0,0,116,9,0,124,0,0,124,2,0,131, - 2,0,125,6,0,124,6,0,100,9,0,107,8,0,114,232, - 0,116,8,0,116,6,0,106,7,0,124,0,0,131,1,0, - 100,4,0,124,0,0,131,1,1,130,1,0,110,62,0,124, - 0,0,116,2,0,106,3,0,107,6,0,114,7,1,116,2, - 0,106,3,0,124,0,0,25,125,7,0,110,31,0,124,6, - 0,106,10,0,124,0,0,131,1,0,125,7,0,116,11,0, - 100,5,0,124,0,0,124,6,0,131,3,0,1,124,3,0, - 114,89,1,116,2,0,106,3,0,124,3,0,25,125,4,0, - 116,12,0,124,4,0,124,0,0,106,1,0,100,1,0,131, - 1,0,100,6,0,25,124,7,0,131,3,0,1,110,0,0, - 116,13,0,124,7,0,100,7,0,131,2,0,12,115,120,1, - 124,7,0,106,14,0,100,9,0,107,8,0,114,203,1,121, - 59,0,124,7,0,106,15,0,124,7,0,95,14,0,116,13, - 0,124,7,0,100,8,0,131,2,0,115,178,1,124,7,0, - 106,14,0,106,1,0,100,1,0,131,1,0,100,2,0,25, - 124,7,0,95,14,0,110,0,0,87,113,203,1,4,116,5, - 0,107,10,0,114,199,1,1,1,1,89,113,203,1,88,110, - 0,0,124,7,0,83,40,10,0,0,0,117,25,0,0,0, - 70,105,110,100,32,97,110,100,32,108,111,97,100,32,116,104, - 101,32,109,111,100,117,108,101,46,117,1,0,0,0,46,105, - 0,0,0,0,117,21,0,0,0,59,32,123,125,32,105,115, - 32,110,111,116,32,97,32,112,97,99,107,97,103,101,117,4, - 0,0,0,110,97,109,101,117,18,0,0,0,105,109,112,111, - 114,116,32,123,33,114,125,32,35,32,123,33,114,125,105,2, - 0,0,0,117,11,0,0,0,95,95,112,97,99,107,97,103, - 101,95,95,117,8,0,0,0,95,95,112,97,116,104,95,95, - 78,40,16,0,0,0,117,4,0,0,0,78,111,110,101,117, - 10,0,0,0,114,112,97,114,116,105,116,105,111,110,117,3, - 0,0,0,115,121,115,117,7,0,0,0,109,111,100,117,108, - 101,115,117,8,0,0,0,95,95,112,97,116,104,95,95,117, - 14,0,0,0,65,116,116,114,105,98,117,116,101,69,114,114, - 111,114,117,8,0,0,0,95,69,82,82,95,77,83,71,117, - 6,0,0,0,102,111,114,109,97,116,117,11,0,0,0,73, - 109,112,111,114,116,69,114,114,111,114,117,12,0,0,0,95, - 102,105,110,100,95,109,111,100,117,108,101,117,11,0,0,0, - 108,111,97,100,95,109,111,100,117,108,101,117,15,0,0,0, - 118,101,114,98,111,115,101,95,109,101,115,115,97,103,101,117, - 7,0,0,0,115,101,116,97,116,116,114,117,7,0,0,0, - 104,97,115,97,116,116,114,117,11,0,0,0,95,95,112,97, - 99,107,97,103,101,95,95,117,8,0,0,0,95,95,110,97, - 109,101,95,95,40,8,0,0,0,117,4,0,0,0,110,97, - 109,101,117,7,0,0,0,105,109,112,111,114,116,95,117,4, - 0,0,0,112,97,116,104,117,6,0,0,0,112,97,114,101, - 110,116,117,13,0,0,0,112,97,114,101,110,116,95,109,111, - 100,117,108,101,117,3,0,0,0,109,115,103,117,6,0,0, - 0,108,111,97,100,101,114,117,6,0,0,0,109,111,100,117, - 108,101,40,0,0,0,0,40,0,0,0,0,117,29,0,0, - 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,14, - 0,0,0,95,102,105,110,100,95,97,110,100,95,108,111,97, - 100,199,3,0,0,115,62,0,0,0,0,2,6,1,19,1, - 6,1,15,1,13,2,15,1,11,2,13,1,3,1,13,1, - 13,1,22,1,26,1,15,1,12,1,30,1,15,2,16,2, - 15,1,16,1,6,2,13,1,32,2,31,1,3,1,12,1, - 15,1,32,1,13,1,8,1,117,14,0,0,0,95,102,105, - 110,100,95,97,110,100,95,108,111,97,100,105,0,0,0,0, - 99,3,0,0,0,0,0,0,0,5,0,0,0,18,0,0, - 0,67,0,0,0,115,172,0,0,0,116,0,0,124,0,0, - 124,1,0,124,2,0,131,3,0,1,124,2,0,100,1,0, - 107,4,0,114,49,0,116,1,0,124,0,0,124,1,0,124, - 2,0,131,3,0,125,0,0,110,0,0,116,2,0,131,0, - 0,143,108,0,1,121,69,0,116,3,0,106,4,0,124,0, - 0,25,125,3,0,124,3,0,100,4,0,107,8,0,114,123, - 0,100,2,0,106,6,0,124,0,0,131,1,0,125,4,0, - 116,7,0,124,4,0,100,3,0,124,0,0,131,1,1,130, - 1,0,110,0,0,124,3,0,83,87,110,18,0,4,116,8, - 0,107,10,0,114,148,0,1,1,1,89,110,1,0,88,116, - 9,0,124,0,0,116,10,0,131,2,0,83,87,100,4,0, - 81,88,100,4,0,83,40,5,0,0,0,117,50,1,0,0, - 73,109,112,111,114,116,32,97,110,100,32,114,101,116,117,114, - 110,32,116,104,101,32,109,111,100,117,108,101,32,98,97,115, - 101,100,32,111,110,32,105,116,115,32,110,97,109,101,44,32, - 116,104,101,32,112,97,99,107,97,103,101,32,116,104,101,32, - 99,97,108,108,32,105,115,10,32,32,32,32,98,101,105,110, - 103,32,109,97,100,101,32,102,114,111,109,44,32,97,110,100, - 32,116,104,101,32,108,101,118,101,108,32,97,100,106,117,115, - 116,109,101,110,116,46,10,10,32,32,32,32,84,104,105,115, - 32,102,117,110,99,116,105,111,110,32,114,101,112,114,101,115, - 101,110,116,115,32,116,104,101,32,103,114,101,97,116,101,115, - 116,32,99,111,109,109,111,110,32,100,101,110,111,109,105,110, - 97,116,111,114,32,111,102,32,102,117,110,99,116,105,111,110, - 97,108,105,116,121,10,32,32,32,32,98,101,116,119,101,101, - 110,32,105,109,112,111,114,116,95,109,111,100,117,108,101,32, - 97,110,100,32,95,95,105,109,112,111,114,116,95,95,46,32, - 84,104,105,115,32,105,110,99,108,117,100,101,115,32,115,101, - 116,116,105,110,103,32,95,95,112,97,99,107,97,103,101,95, - 95,32,105,102,10,32,32,32,32,116,104,101,32,108,111,97, - 100,101,114,32,100,105,100,32,110,111,116,46,10,10,32,32, - 32,32,105,0,0,0,0,117,40,0,0,0,105,109,112,111, - 114,116,32,111,102,32,123,125,32,104,97,108,116,101,100,59, - 32,78,111,110,101,32,105,110,32,115,121,115,46,109,111,100, - 117,108,101,115,117,4,0,0,0,110,97,109,101,78,40,11, - 0,0,0,117,13,0,0,0,95,115,97,110,105,116,121,95, - 99,104,101,99,107,117,13,0,0,0,95,114,101,115,111,108, - 118,101,95,110,97,109,101,117,18,0,0,0,95,73,109,112, - 111,114,116,76,111,99,107,67,111,110,116,101,120,116,117,3, - 0,0,0,115,121,115,117,7,0,0,0,109,111,100,117,108, - 101,115,117,4,0,0,0,78,111,110,101,117,6,0,0,0, - 102,111,114,109,97,116,117,11,0,0,0,73,109,112,111,114, - 116,69,114,114,111,114,117,8,0,0,0,75,101,121,69,114, - 114,111,114,117,14,0,0,0,95,102,105,110,100,95,97,110, - 100,95,108,111,97,100,117,11,0,0,0,95,103,99,100,95, - 105,109,112,111,114,116,40,5,0,0,0,117,4,0,0,0, - 110,97,109,101,117,7,0,0,0,112,97,99,107,97,103,101, - 117,5,0,0,0,108,101,118,101,108,117,6,0,0,0,109, - 111,100,117,108,101,117,7,0,0,0,109,101,115,115,97,103, - 101,40,0,0,0,0,40,0,0,0,0,117,29,0,0,0, - 60,102,114,111,122,101,110,32,105,109,112,111,114,116,108,105, - 98,46,95,98,111,111,116,115,116,114,97,112,62,117,11,0, - 0,0,95,103,99,100,95,105,109,112,111,114,116,240,3,0, - 0,115,28,0,0,0,0,9,16,1,12,1,21,1,10,1, - 3,1,13,1,12,1,6,1,9,1,21,1,8,1,13,1, - 5,1,117,11,0,0,0,95,103,99,100,95,105,109,112,111, - 114,116,99,3,0,0,0,0,0,0,0,4,0,0,0,13, - 0,0,0,3,0,0,0,115,179,0,0,0,116,0,0,136, - 0,0,100,1,0,131,2,0,114,175,0,100,2,0,124,1, - 0,107,6,0,114,86,0,116,0,0,136,0,0,100,3,0, - 131,2,0,114,86,0,116,1,0,124,1,0,131,1,0,125, - 1,0,124,1,0,106,2,0,100,2,0,131,1,0,1,124, - 1,0,106,3,0,136,0,0,106,4,0,131,1,0,1,110, - 0,0,120,86,0,135,0,0,102,1,0,100,4,0,100,5, - 0,134,0,0,124,1,0,68,131,1,0,68,93,56,0,125, - 3,0,121,29,0,124,2,0,100,6,0,106,5,0,136,0, - 0,106,6,0,124,3,0,131,2,0,131,1,0,1,87,113, - 112,0,4,116,7,0,107,10,0,114,167,0,1,1,1,89, - 113,112,0,88,113,112,0,87,110,0,0,136,0,0,83,40, - 7,0,0,0,117,238,0,0,0,70,105,103,117,114,101,32, - 111,117,116,32,119,104,97,116,32,95,95,105,109,112,111,114, - 116,95,95,32,115,104,111,117,108,100,32,114,101,116,117,114, - 110,46,10,10,32,32,32,32,84,104,101,32,105,109,112,111, - 114,116,95,32,112,97,114,97,109,101,116,101,114,32,105,115, - 32,97,32,99,97,108,108,97,98,108,101,32,119,104,105,99, - 104,32,116,97,107,101,115,32,116,104,101,32,110,97,109,101, - 32,111,102,32,109,111,100,117,108,101,32,116,111,10,32,32, - 32,32,105,109,112,111,114,116,46,32,73,116,32,105,115,32, - 114,101,113,117,105,114,101,100,32,116,111,32,100,101,99,111, - 117,112,108,101,32,116,104,101,32,102,117,110,99,116,105,111, - 110,32,102,114,111,109,32,97,115,115,117,109,105,110,103,32, - 105,109,112,111,114,116,108,105,98,39,115,10,32,32,32,32, - 105,109,112,111,114,116,32,105,109,112,108,101,109,101,110,116, - 97,116,105,111,110,32,105,115,32,100,101,115,105,114,101,100, - 46,10,10,32,32,32,32,117,8,0,0,0,95,95,112,97, - 116,104,95,95,117,1,0,0,0,42,117,7,0,0,0,95, - 95,97,108,108,95,95,99,1,0,0,0,0,0,0,0,2, - 0,0,0,4,0,0,0,51,0,0,0,115,36,0,0,0, - 124,0,0,93,26,0,125,1,0,116,0,0,136,0,0,124, - 1,0,131,2,0,115,3,0,124,1,0,86,1,113,3,0, - 100,0,0,83,40,1,0,0,0,78,40,1,0,0,0,117, - 7,0,0,0,104,97,115,97,116,116,114,40,2,0,0,0, - 117,2,0,0,0,46,48,117,1,0,0,0,121,40,1,0, - 0,0,117,6,0,0,0,109,111,100,117,108,101,40,0,0, - 0,0,117,29,0,0,0,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,117,9,0,0,0,60,103,101,110,101,120,112, - 114,62,24,4,0,0,115,2,0,0,0,6,0,117,35,0, - 0,0,95,104,97,110,100,108,101,95,102,114,111,109,108,105, - 115,116,46,60,108,111,99,97,108,115,62,46,60,103,101,110, - 101,120,112,114,62,117,7,0,0,0,123,48,125,46,123,49, - 125,40,8,0,0,0,117,7,0,0,0,104,97,115,97,116, - 116,114,117,4,0,0,0,108,105,115,116,117,6,0,0,0, - 114,101,109,111,118,101,117,6,0,0,0,101,120,116,101,110, - 100,117,7,0,0,0,95,95,97,108,108,95,95,117,6,0, - 0,0,102,111,114,109,97,116,117,8,0,0,0,95,95,110, - 97,109,101,95,95,117,11,0,0,0,73,109,112,111,114,116, - 69,114,114,111,114,40,4,0,0,0,117,6,0,0,0,109, - 111,100,117,108,101,117,8,0,0,0,102,114,111,109,108,105, - 115,116,117,7,0,0,0,105,109,112,111,114,116,95,117,1, - 0,0,0,120,40,0,0,0,0,40,1,0,0,0,117,6, - 0,0,0,109,111,100,117,108,101,117,29,0,0,0,60,102, - 114,111,122,101,110,32,105,109,112,111,114,116,108,105,98,46, - 95,98,111,111,116,115,116,114,97,112,62,117,16,0,0,0, - 95,104,97,110,100,108,101,95,102,114,111,109,108,105,115,116, - 9,4,0,0,115,22,0,0,0,0,10,15,1,27,1,12, - 1,13,1,19,1,32,1,3,1,29,1,13,1,12,1,117, - 16,0,0,0,95,104,97,110,100,108,101,95,102,114,111,109, - 108,105,115,116,99,1,0,0,0,0,0,0,0,2,0,0, - 0,2,0,0,0,67,0,0,0,115,78,0,0,0,124,0, - 0,106,0,0,100,1,0,131,1,0,125,1,0,124,1,0, - 100,6,0,107,8,0,114,74,0,124,0,0,100,2,0,25, - 125,1,0,100,3,0,124,0,0,107,7,0,114,74,0,124, - 1,0,106,2,0,100,4,0,131,1,0,100,5,0,25,125, - 1,0,113,74,0,110,0,0,124,1,0,83,40,7,0,0, - 0,117,167,0,0,0,67,97,108,99,117,108,97,116,101,32, - 119,104,97,116,32,95,95,112,97,99,107,97,103,101,95,95, - 32,115,104,111,117,108,100,32,98,101,46,10,10,32,32,32, - 32,95,95,112,97,99,107,97,103,101,95,95,32,105,115,32, - 110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116, - 111,32,98,101,32,100,101,102,105,110,101,100,32,111,114,32, - 99,111,117,108,100,32,98,101,32,115,101,116,32,116,111,32, - 78,111,110,101,10,32,32,32,32,116,111,32,114,101,112,114, - 101,115,101,110,116,32,116,104,97,116,32,105,116,115,32,112, - 114,111,112,101,114,32,118,97,108,117,101,32,105,115,32,117, - 110,107,110,111,119,110,46,10,10,32,32,32,32,117,11,0, - 0,0,95,95,112,97,99,107,97,103,101,95,95,117,8,0, - 0,0,95,95,110,97,109,101,95,95,117,8,0,0,0,95, - 95,112,97,116,104,95,95,117,1,0,0,0,46,105,0,0, - 0,0,78,40,3,0,0,0,117,3,0,0,0,103,101,116, - 117,4,0,0,0,78,111,110,101,117,10,0,0,0,114,112, - 97,114,116,105,116,105,111,110,40,2,0,0,0,117,7,0, - 0,0,103,108,111,98,97,108,115,117,7,0,0,0,112,97, - 99,107,97,103,101,40,0,0,0,0,40,0,0,0,0,117, + 6,0,0,0,95,115,101,116,117,112,81,4,0,0,115,52, + 0,0,0,0,9,6,1,6,2,19,1,15,1,16,2,13, + 1,13,1,15,1,18,2,13,1,20,2,28,1,15,1,13, + 1,4,2,3,1,15,2,27,1,9,1,5,1,13,1,12, + 2,12,1,16,1,16,2,117,6,0,0,0,95,115,101,116, + 117,112,99,2,0,0,0,0,0,0,0,3,0,0,0,3, + 0,0,0,67,0,0,0,115,44,0,0,0,116,0,0,124, + 0,0,124,1,0,131,2,0,1,116,1,0,106,2,0,125, + 2,0,116,2,0,116,1,0,95,2,0,124,2,0,116,1, + 0,95,3,0,100,1,0,83,40,2,0,0,0,117,202,0, + 0,0,73,110,115,116,97,108,108,32,105,109,112,111,114,116, + 108,105,98,32,97,115,32,116,104,101,32,105,109,112,108,101, + 109,101,110,116,97,116,105,111,110,32,111,102,32,105,109,112, + 111,114,116,46,10,10,32,32,32,32,73,116,32,105,115,32, + 97,115,115,117,109,101,100,32,116,104,97,116,32,95,105,109, + 112,32,97,110,100,32,115,121,115,32,104,97,118,101,32,98, + 101,101,110,32,105,109,112,111,114,116,101,100,32,97,110,100, + 32,105,110,106,101,99,116,101,100,32,105,110,116,111,32,116, + 104,101,10,32,32,32,32,103,108,111,98,97,108,32,110,97, + 109,101,115,112,97,99,101,32,102,111,114,32,116,104,101,32, + 109,111,100,117,108,101,32,112,114,105,111,114,32,116,111,32, + 99,97,108,108,105,110,103,32,116,104,105,115,32,102,117,110, + 99,116,105,111,110,46,10,10,32,32,32,32,78,40,4,0, + 0,0,117,6,0,0,0,95,115,101,116,117,112,117,8,0, + 0,0,98,117,105,108,116,105,110,115,117,10,0,0,0,95, + 95,105,109,112,111,114,116,95,95,117,19,0,0,0,95,95, + 111,114,105,103,105,110,97,108,95,105,109,112,111,114,116,95, + 95,40,3,0,0,0,117,10,0,0,0,115,121,115,95,109, + 111,100,117,108,101,117,11,0,0,0,95,105,109,112,95,109, + 111,100,117,108,101,117,11,0,0,0,111,114,105,103,95,105, + 109,112,111,114,116,40,0,0,0,0,40,0,0,0,0,117, 29,0,0,0,60,102,114,111,122,101,110,32,105,109,112,111, 114,116,108,105,98,46,95,98,111,111,116,115,116,114,97,112, - 62,117,17,0,0,0,95,99,97,108,99,95,95,95,112,97, - 99,107,97,103,101,95,95,32,4,0,0,115,12,0,0,0, - 0,7,15,1,12,1,10,1,12,1,25,1,117,17,0,0, - 0,95,99,97,108,99,95,95,95,112,97,99,107,97,103,101, - 95,95,99,5,0,0,0,0,0,0,0,9,0,0,0,5, - 0,0,0,67,0,0,0,115,235,0,0,0,124,4,0,100, - 1,0,107,2,0,114,27,0,116,0,0,124,0,0,131,1, - 0,125,5,0,110,30,0,116,1,0,124,1,0,131,1,0, - 125,6,0,116,0,0,124,0,0,124,6,0,124,4,0,131, - 3,0,125,5,0,124,3,0,115,215,0,124,4,0,100,1, - 0,107,2,0,114,130,0,124,0,0,106,2,0,100,2,0, - 131,1,0,125,7,0,124,7,0,100,5,0,107,2,0,114, - 106,0,124,5,0,83,116,3,0,106,4,0,124,0,0,100, - 4,0,124,7,0,133,2,0,25,25,83,113,231,0,124,0, - 0,115,140,0,124,5,0,83,116,5,0,124,0,0,131,1, - 0,116,5,0,124,0,0,106,6,0,100,2,0,131,1,0, - 100,1,0,25,131,1,0,24,125,8,0,116,3,0,106,4, - 0,124,5,0,106,7,0,100,4,0,116,5,0,124,5,0, - 106,7,0,131,1,0,124,8,0,24,133,2,0,25,25,83, - 110,16,0,116,8,0,124,5,0,124,3,0,116,0,0,131, - 3,0,83,100,4,0,83,40,6,0,0,0,117,214,1,0, - 0,73,109,112,111,114,116,32,97,32,109,111,100,117,108,101, - 46,10,10,32,32,32,32,84,104,101,32,39,103,108,111,98, - 97,108,115,39,32,97,114,103,117,109,101,110,116,32,105,115, - 32,117,115,101,100,32,116,111,32,105,110,102,101,114,32,119, - 104,101,114,101,32,116,104,101,32,105,109,112,111,114,116,32, - 105,115,32,111,99,99,117,114,105,110,103,32,102,114,111,109, - 10,32,32,32,32,116,111,32,104,97,110,100,108,101,32,114, - 101,108,97,116,105,118,101,32,105,109,112,111,114,116,115,46, - 32,84,104,101,32,39,108,111,99,97,108,115,39,32,97,114, - 103,117,109,101,110,116,32,105,115,32,105,103,110,111,114,101, - 100,46,32,84,104,101,10,32,32,32,32,39,102,114,111,109, - 108,105,115,116,39,32,97,114,103,117,109,101,110,116,32,115, - 112,101,99,105,102,105,101,115,32,119,104,97,116,32,115,104, - 111,117,108,100,32,101,120,105,115,116,32,97,115,32,97,116, - 116,114,105,98,117,116,101,115,32,111,110,32,116,104,101,32, - 109,111,100,117,108,101,10,32,32,32,32,98,101,105,110,103, - 32,105,109,112,111,114,116,101,100,32,40,101,46,103,46,32, - 96,96,102,114,111,109,32,109,111,100,117,108,101,32,105,109, - 112,111,114,116,32,60,102,114,111,109,108,105,115,116,62,96, - 96,41,46,32,32,84,104,101,32,39,108,101,118,101,108,39, - 10,32,32,32,32,97,114,103,117,109,101,110,116,32,114,101, - 112,114,101,115,101,110,116,115,32,116,104,101,32,112,97,99, - 107,97,103,101,32,108,111,99,97,116,105,111,110,32,116,111, - 32,105,109,112,111,114,116,32,102,114,111,109,32,105,110,32, - 97,32,114,101,108,97,116,105,118,101,10,32,32,32,32,105, - 109,112,111,114,116,32,40,101,46,103,46,32,96,96,102,114, - 111,109,32,46,46,112,107,103,32,105,109,112,111,114,116,32, - 109,111,100,96,96,32,119,111,117,108,100,32,104,97,118,101, - 32,97,32,39,108,101,118,101,108,39,32,111,102,32,50,41, - 46,10,10,32,32,32,32,105,0,0,0,0,117,1,0,0, - 0,46,105,1,0,0,0,78,105,255,255,255,255,40,9,0, - 0,0,117,11,0,0,0,95,103,99,100,95,105,109,112,111, - 114,116,117,17,0,0,0,95,99,97,108,99,95,95,95,112, - 97,99,107,97,103,101,95,95,117,4,0,0,0,102,105,110, - 100,117,3,0,0,0,115,121,115,117,7,0,0,0,109,111, - 100,117,108,101,115,117,3,0,0,0,108,101,110,117,9,0, - 0,0,112,97,114,116,105,116,105,111,110,117,8,0,0,0, - 95,95,110,97,109,101,95,95,117,16,0,0,0,95,104,97, - 110,100,108,101,95,102,114,111,109,108,105,115,116,40,9,0, - 0,0,117,4,0,0,0,110,97,109,101,117,7,0,0,0, - 103,108,111,98,97,108,115,117,6,0,0,0,108,111,99,97, - 108,115,117,8,0,0,0,102,114,111,109,108,105,115,116,117, - 5,0,0,0,108,101,118,101,108,117,6,0,0,0,109,111, - 100,117,108,101,117,7,0,0,0,112,97,99,107,97,103,101, - 117,5,0,0,0,105,110,100,101,120,117,7,0,0,0,99, - 117,116,95,111,102,102,40,0,0,0,0,40,0,0,0,0, - 117,29,0,0,0,60,102,114,111,122,101,110,32,105,109,112, - 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, - 112,62,117,10,0,0,0,95,95,105,109,112,111,114,116,95, - 95,47,4,0,0,115,30,0,0,0,0,11,12,1,15,2, - 12,1,18,1,6,3,12,1,15,1,12,1,4,2,24,1, - 6,1,4,2,35,1,40,2,117,10,0,0,0,95,95,105, - 109,112,111,114,116,95,95,99,2,0,0,0,0,0,0,0, - 9,0,0,0,12,0,0,0,67,0,0,0,115,109,1,0, - 0,124,1,0,97,0,0,124,0,0,97,1,0,120,47,0, - 116,0,0,116,1,0,102,2,0,68,93,33,0,125,2,0, - 116,2,0,124,2,0,100,1,0,131,2,0,115,25,0,116, - 3,0,124,2,0,95,4,0,113,25,0,113,25,0,87,116, - 1,0,106,5,0,116,6,0,25,125,3,0,120,76,0,100, - 17,0,68,93,68,0,125,4,0,124,4,0,116,1,0,106, - 5,0,107,7,0,114,121,0,116,3,0,106,7,0,124,4, - 0,131,1,0,125,5,0,110,13,0,116,1,0,106,5,0, - 124,4,0,25,125,5,0,116,8,0,124,3,0,124,4,0, - 124,5,0,131,3,0,1,113,82,0,87,120,153,0,100,18, - 0,100,19,0,100,20,0,103,3,0,68,93,124,0,92,2, - 0,125,6,0,125,7,0,124,6,0,116,1,0,106,5,0, - 107,6,0,114,214,0,116,1,0,106,5,0,124,6,0,25, - 125,8,0,80,113,170,0,121,56,0,116,3,0,106,7,0, - 124,6,0,131,1,0,125,8,0,124,6,0,100,10,0,107, - 2,0,114,12,1,100,11,0,116,1,0,106,9,0,107,6, - 0,114,12,1,100,7,0,125,7,0,110,0,0,80,87,113, - 170,0,4,116,10,0,107,10,0,114,37,1,1,1,1,119, - 170,0,89,113,170,0,88,113,170,0,87,116,10,0,100,12, - 0,131,1,0,130,1,0,116,8,0,124,3,0,100,13,0, - 124,8,0,131,3,0,1,116,8,0,124,3,0,100,14,0, - 124,7,0,131,3,0,1,116,8,0,124,3,0,100,15,0, - 116,11,0,131,0,0,131,3,0,1,100,16,0,83,40,21, - 0,0,0,117,250,0,0,0,83,101,116,117,112,32,105,109, - 112,111,114,116,108,105,98,32,98,121,32,105,109,112,111,114, - 116,105,110,103,32,110,101,101,100,101,100,32,98,117,105,108, - 116,45,105,110,32,109,111,100,117,108,101,115,32,97,110,100, - 32,105,110,106,101,99,116,105,110,103,32,116,104,101,109,10, - 32,32,32,32,105,110,116,111,32,116,104,101,32,103,108,111, - 98,97,108,32,110,97,109,101,115,112,97,99,101,46,10,10, - 32,32,32,32,65,115,32,115,121,115,32,105,115,32,110,101, - 101,100,101,100,32,102,111,114,32,115,121,115,46,109,111,100, - 117,108,101,115,32,97,99,99,101,115,115,32,97,110,100,32, - 95,105,109,112,32,105,115,32,110,101,101,100,101,100,32,116, - 111,32,108,111,97,100,32,98,117,105,108,116,45,105,110,10, - 32,32,32,32,109,111,100,117,108,101,115,44,32,116,104,111, - 115,101,32,116,119,111,32,109,111,100,117,108,101,115,32,109, - 117,115,116,32,98,101,32,101,120,112,108,105,99,105,116,108, - 121,32,112,97,115,115,101,100,32,105,110,46,10,10,32,32, - 32,32,117,10,0,0,0,95,95,108,111,97,100,101,114,95, - 95,117,3,0,0,0,95,105,111,117,9,0,0,0,95,119, - 97,114,110,105,110,103,115,117,8,0,0,0,98,117,105,108, - 116,105,110,115,117,7,0,0,0,109,97,114,115,104,97,108, - 117,5,0,0,0,112,111,115,105,120,117,1,0,0,0,47, - 117,2,0,0,0,110,116,117,1,0,0,0,92,117,3,0, - 0,0,111,115,50,117,7,0,0,0,69,77,88,32,71,67, - 67,117,30,0,0,0,105,109,112,111,114,116,108,105,98,32, - 114,101,113,117,105,114,101,115,32,112,111,115,105,120,32,111, - 114,32,110,116,117,3,0,0,0,95,111,115,117,8,0,0, - 0,112,97,116,104,95,115,101,112,117,11,0,0,0,95,114, - 101,108,97,120,95,99,97,115,101,78,40,4,0,0,0,117, - 3,0,0,0,95,105,111,117,9,0,0,0,95,119,97,114, - 110,105,110,103,115,117,8,0,0,0,98,117,105,108,116,105, - 110,115,117,7,0,0,0,109,97,114,115,104,97,108,40,2, - 0,0,0,117,5,0,0,0,112,111,115,105,120,117,1,0, - 0,0,47,40,2,0,0,0,117,2,0,0,0,110,116,117, - 1,0,0,0,92,40,2,0,0,0,117,3,0,0,0,111, - 115,50,117,1,0,0,0,92,40,12,0,0,0,117,4,0, - 0,0,95,105,109,112,117,3,0,0,0,115,121,115,117,7, - 0,0,0,104,97,115,97,116,116,114,117,15,0,0,0,66, - 117,105,108,116,105,110,73,109,112,111,114,116,101,114,117,10, - 0,0,0,95,95,108,111,97,100,101,114,95,95,117,7,0, - 0,0,109,111,100,117,108,101,115,117,8,0,0,0,95,95, - 110,97,109,101,95,95,117,11,0,0,0,108,111,97,100,95, - 109,111,100,117,108,101,117,7,0,0,0,115,101,116,97,116, - 116,114,117,7,0,0,0,118,101,114,115,105,111,110,117,11, - 0,0,0,73,109,112,111,114,116,69,114,114,111,114,117,16, - 0,0,0,95,109,97,107,101,95,114,101,108,97,120,95,99, - 97,115,101,40,9,0,0,0,117,10,0,0,0,115,121,115, - 95,109,111,100,117,108,101,117,11,0,0,0,95,105,109,112, - 95,109,111,100,117,108,101,117,6,0,0,0,109,111,100,117, - 108,101,117,11,0,0,0,115,101,108,102,95,109,111,100,117, - 108,101,117,12,0,0,0,98,117,105,108,116,105,110,95,110, - 97,109,101,117,14,0,0,0,98,117,105,108,116,105,110,95, - 109,111,100,117,108,101,117,10,0,0,0,98,117,105,108,116, - 105,110,95,111,115,117,8,0,0,0,112,97,116,104,95,115, - 101,112,117,9,0,0,0,111,115,95,109,111,100,117,108,101, - 40,0,0,0,0,40,0,0,0,0,117,29,0,0,0,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,117,6,0,0, - 0,95,115,101,116,117,112,81,4,0,0,115,52,0,0,0, - 0,9,6,1,6,2,19,1,15,1,16,2,13,1,13,1, - 15,1,18,2,13,1,20,2,28,1,15,1,13,1,4,2, - 3,1,15,2,27,1,9,1,5,1,13,1,12,2,12,1, - 16,1,16,2,117,6,0,0,0,95,115,101,116,117,112,99, - 2,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, - 67,0,0,0,115,44,0,0,0,116,0,0,124,0,0,124, - 1,0,131,2,0,1,116,1,0,106,2,0,125,2,0,116, - 2,0,116,1,0,95,2,0,124,2,0,116,1,0,95,3, - 0,100,1,0,83,40,2,0,0,0,117,202,0,0,0,73, - 110,115,116,97,108,108,32,105,109,112,111,114,116,108,105,98, - 32,97,115,32,116,104,101,32,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,32,111,102,32,105,109,112,111,114,116, - 46,10,10,32,32,32,32,73,116,32,105,115,32,97,115,115, - 117,109,101,100,32,116,104,97,116,32,95,105,109,112,32,97, - 110,100,32,115,121,115,32,104,97,118,101,32,98,101,101,110, - 32,105,109,112,111,114,116,101,100,32,97,110,100,32,105,110, - 106,101,99,116,101,100,32,105,110,116,111,32,116,104,101,10, - 32,32,32,32,103,108,111,98,97,108,32,110,97,109,101,115, - 112,97,99,101,32,102,111,114,32,116,104,101,32,109,111,100, - 117,108,101,32,112,114,105,111,114,32,116,111,32,99,97,108, - 108,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105, - 111,110,46,10,10,32,32,32,32,78,40,4,0,0,0,117, - 6,0,0,0,95,115,101,116,117,112,117,8,0,0,0,98, - 117,105,108,116,105,110,115,117,10,0,0,0,95,95,105,109, - 112,111,114,116,95,95,117,19,0,0,0,95,95,111,114,105, - 103,105,110,97,108,95,105,109,112,111,114,116,95,95,40,3, - 0,0,0,117,10,0,0,0,115,121,115,95,109,111,100,117, - 108,101,117,11,0,0,0,95,105,109,112,95,109,111,100,117, - 108,101,117,11,0,0,0,111,114,105,103,95,105,109,112,111, - 114,116,40,0,0,0,0,40,0,0,0,0,117,29,0,0, - 0,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,62,117,8, - 0,0,0,95,105,110,115,116,97,108,108,126,4,0,0,115, - 8,0,0,0,0,7,13,1,9,1,9,1,117,8,0,0, - 0,95,105,110,115,116,97,108,108,78,40,3,0,0,0,117, - 3,0,0,0,119,105,110,117,6,0,0,0,99,121,103,119, - 105,110,117,6,0,0,0,100,97,114,119,105,110,40,56,0, - 0,0,117,7,0,0,0,95,95,100,111,99,95,95,117,26, - 0,0,0,67,65,83,69,95,73,78,83,69,78,83,73,84, - 73,86,69,95,80,76,65,84,70,79,82,77,83,117,16,0, - 0,0,95,109,97,107,101,95,114,101,108,97,120,95,99,97, - 115,101,117,7,0,0,0,95,119,95,108,111,110,103,117,7, - 0,0,0,95,114,95,108,111,110,103,117,10,0,0,0,95, - 112,97,116,104,95,106,111,105,110,117,12,0,0,0,95,112, - 97,116,104,95,101,120,105,115,116,115,117,18,0,0,0,95, - 112,97,116,104,95,105,115,95,109,111,100,101,95,116,121,112, - 101,117,12,0,0,0,95,112,97,116,104,95,105,115,102,105, - 108,101,117,11,0,0,0,95,112,97,116,104,95,105,115,100, - 105,114,117,17,0,0,0,95,112,97,116,104,95,119,105,116, - 104,111,117,116,95,101,120,116,117,14,0,0,0,95,112,97, - 116,104,95,97,98,115,111,108,117,116,101,117,13,0,0,0, - 95,119,114,105,116,101,95,97,116,111,109,105,99,117,5,0, - 0,0,95,119,114,97,112,117,4,0,0,0,116,121,112,101, - 117,8,0,0,0,95,95,99,111,100,101,95,95,117,9,0, - 0,0,99,111,100,101,95,116,121,112,101,117,10,0,0,0, - 110,101,119,95,109,111,100,117,108,101,117,15,0,0,0,118, - 101,114,98,111,115,101,95,109,101,115,115,97,103,101,117,11, - 0,0,0,115,101,116,95,112,97,99,107,97,103,101,117,10, - 0,0,0,115,101,116,95,108,111,97,100,101,114,117,17,0, - 0,0,109,111,100,117,108,101,95,102,111,114,95,108,111,97, - 100,101,114,117,11,0,0,0,95,99,104,101,99,107,95,110, - 97,109,101,117,17,0,0,0,95,114,101,113,117,105,114,101, - 115,95,98,117,105,108,116,105,110,117,16,0,0,0,95,114, - 101,113,117,105,114,101,115,95,102,114,111,122,101,110,117,12, - 0,0,0,95,115,117,102,102,105,120,95,108,105,115,116,117, - 15,0,0,0,66,117,105,108,116,105,110,73,109,112,111,114, - 116,101,114,117,14,0,0,0,70,114,111,122,101,110,73,109, - 112,111,114,116,101,114,117,13,0,0,0,95,76,111,97,100, - 101,114,66,97,115,105,99,115,117,12,0,0,0,83,111,117, - 114,99,101,76,111,97,100,101,114,117,11,0,0,0,95,70, - 105,108,101,76,111,97,100,101,114,117,17,0,0,0,95,83, - 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,117, - 21,0,0,0,95,83,111,117,114,99,101,108,101,115,115,70, - 105,108,101,76,111,97,100,101,114,117,20,0,0,0,95,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,117,10,0,0,0,80,97,116,104,70,105,110,100,101, - 114,117,11,0,0,0,95,70,105,108,101,70,105,110,100,101, - 114,117,20,0,0,0,95,83,111,117,114,99,101,70,105,110, - 100,101,114,68,101,116,97,105,108,115,117,24,0,0,0,95, - 83,111,117,114,99,101,108,101,115,115,70,105,110,100,101,114, - 68,101,116,97,105,108,115,117,23,0,0,0,95,69,120,116, - 101,110,115,105,111,110,70,105,110,100,101,114,68,101,116,97, - 105,108,115,117,15,0,0,0,95,102,105,108,101,95,112,97, - 116,104,95,104,111,111,107,117,18,0,0,0,95,68,69,70, - 65,85,76,84,95,80,65,84,72,95,72,79,79,75,117,18, - 0,0,0,95,68,101,102,97,117,108,116,80,97,116,104,70, - 105,110,100,101,114,117,18,0,0,0,95,73,109,112,111,114, - 116,76,111,99,107,67,111,110,116,101,120,116,117,13,0,0, - 0,95,114,101,115,111,108,118,101,95,110,97,109,101,117,12, - 0,0,0,95,102,105,110,100,95,109,111,100,117,108,101,117, - 13,0,0,0,95,115,97,110,105,116,121,95,99,104,101,99, - 107,117,19,0,0,0,95,73,77,80,76,73,67,73,84,95, - 77,69,84,65,95,80,65,84,72,117,8,0,0,0,95,69, - 82,82,95,77,83,71,117,14,0,0,0,95,102,105,110,100, - 95,97,110,100,95,108,111,97,100,117,4,0,0,0,78,111, - 110,101,117,11,0,0,0,95,103,99,100,95,105,109,112,111, - 114,116,117,16,0,0,0,95,104,97,110,100,108,101,95,102, - 114,111,109,108,105,115,116,117,17,0,0,0,95,99,97,108, - 99,95,95,95,112,97,99,107,97,103,101,95,95,117,10,0, - 0,0,95,95,105,109,112,111,114,116,95,95,117,6,0,0, - 0,95,115,101,116,117,112,117,8,0,0,0,95,105,110,115, - 116,97,108,108,40,0,0,0,0,40,0,0,0,0,40,0, - 0,0,0,117,29,0,0,0,60,102,114,111,122,101,110,32, - 105,109,112,111,114,116,108,105,98,46,95,98,111,111,116,115, - 116,114,97,112,62,117,8,0,0,0,60,109,111,100,117,108, - 101,62,8,0,0,0,115,104,0,0,0,6,14,6,3,12, - 13,12,16,12,15,12,6,12,10,12,10,12,6,12,7,12, - 9,12,13,12,21,12,8,15,3,12,11,12,8,12,13,12, - 11,12,32,12,16,12,11,12,11,12,8,19,53,19,47,19, - 77,22,114,19,22,25,38,25,24,19,45,19,68,19,77,19, - 8,19,9,19,11,12,10,6,2,22,21,19,13,12,9,12, - 15,12,17,15,2,6,2,12,41,18,25,12,23,12,15,24, - 34,12,45, + 62,117,8,0,0,0,95,105,110,115,116,97,108,108,126,4, + 0,0,115,8,0,0,0,0,7,13,1,9,1,9,1,117, + 8,0,0,0,95,105,110,115,116,97,108,108,78,40,3,0, + 0,0,117,3,0,0,0,119,105,110,117,6,0,0,0,99, + 121,103,119,105,110,117,6,0,0,0,100,97,114,119,105,110, + 40,56,0,0,0,117,7,0,0,0,95,95,100,111,99,95, + 95,117,26,0,0,0,67,65,83,69,95,73,78,83,69,78, + 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, + 117,16,0,0,0,95,109,97,107,101,95,114,101,108,97,120, + 95,99,97,115,101,117,7,0,0,0,95,119,95,108,111,110, + 103,117,7,0,0,0,95,114,95,108,111,110,103,117,10,0, + 0,0,95,112,97,116,104,95,106,111,105,110,117,12,0,0, + 0,95,112,97,116,104,95,101,120,105,115,116,115,117,18,0, + 0,0,95,112,97,116,104,95,105,115,95,109,111,100,101,95, + 116,121,112,101,117,12,0,0,0,95,112,97,116,104,95,105, + 115,102,105,108,101,117,11,0,0,0,95,112,97,116,104,95, + 105,115,100,105,114,117,17,0,0,0,95,112,97,116,104,95, + 119,105,116,104,111,117,116,95,101,120,116,117,14,0,0,0, + 95,112,97,116,104,95,97,98,115,111,108,117,116,101,117,13, + 0,0,0,95,119,114,105,116,101,95,97,116,111,109,105,99, + 117,5,0,0,0,95,119,114,97,112,117,4,0,0,0,116, + 121,112,101,117,8,0,0,0,95,95,99,111,100,101,95,95, + 117,9,0,0,0,99,111,100,101,95,116,121,112,101,117,11, + 0,0,0,95,110,101,119,95,109,111,100,117,108,101,117,15, + 0,0,0,118,101,114,98,111,115,101,95,109,101,115,115,97, + 103,101,117,11,0,0,0,115,101,116,95,112,97,99,107,97, + 103,101,117,10,0,0,0,115,101,116,95,108,111,97,100,101, + 114,117,17,0,0,0,109,111,100,117,108,101,95,102,111,114, + 95,108,111,97,100,101,114,117,11,0,0,0,95,99,104,101, + 99,107,95,110,97,109,101,117,17,0,0,0,95,114,101,113, + 117,105,114,101,115,95,98,117,105,108,116,105,110,117,16,0, + 0,0,95,114,101,113,117,105,114,101,115,95,102,114,111,122, + 101,110,117,12,0,0,0,95,115,117,102,102,105,120,95,108, + 105,115,116,117,15,0,0,0,66,117,105,108,116,105,110,73, + 109,112,111,114,116,101,114,117,14,0,0,0,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,117,13,0,0,0,95, + 76,111,97,100,101,114,66,97,115,105,99,115,117,12,0,0, + 0,83,111,117,114,99,101,76,111,97,100,101,114,117,11,0, + 0,0,95,70,105,108,101,76,111,97,100,101,114,117,17,0, + 0,0,95,83,111,117,114,99,101,70,105,108,101,76,111,97, + 100,101,114,117,21,0,0,0,95,83,111,117,114,99,101,108, + 101,115,115,70,105,108,101,76,111,97,100,101,114,117,20,0, + 0,0,95,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,117,10,0,0,0,80,97,116,104,70, + 105,110,100,101,114,117,11,0,0,0,95,70,105,108,101,70, + 105,110,100,101,114,117,20,0,0,0,95,83,111,117,114,99, + 101,70,105,110,100,101,114,68,101,116,97,105,108,115,117,24, + 0,0,0,95,83,111,117,114,99,101,108,101,115,115,70,105, + 110,100,101,114,68,101,116,97,105,108,115,117,23,0,0,0, + 95,69,120,116,101,110,115,105,111,110,70,105,110,100,101,114, + 68,101,116,97,105,108,115,117,15,0,0,0,95,102,105,108, + 101,95,112,97,116,104,95,104,111,111,107,117,18,0,0,0, + 95,68,69,70,65,85,76,84,95,80,65,84,72,95,72,79, + 79,75,117,18,0,0,0,95,68,101,102,97,117,108,116,80, + 97,116,104,70,105,110,100,101,114,117,18,0,0,0,95,73, + 109,112,111,114,116,76,111,99,107,67,111,110,116,101,120,116, + 117,13,0,0,0,95,114,101,115,111,108,118,101,95,110,97, + 109,101,117,12,0,0,0,95,102,105,110,100,95,109,111,100, + 117,108,101,117,13,0,0,0,95,115,97,110,105,116,121,95, + 99,104,101,99,107,117,19,0,0,0,95,73,77,80,76,73, + 67,73,84,95,77,69,84,65,95,80,65,84,72,117,8,0, + 0,0,95,69,82,82,95,77,83,71,117,14,0,0,0,95, + 102,105,110,100,95,97,110,100,95,108,111,97,100,117,4,0, + 0,0,78,111,110,101,117,11,0,0,0,95,103,99,100,95, + 105,109,112,111,114,116,117,16,0,0,0,95,104,97,110,100, + 108,101,95,102,114,111,109,108,105,115,116,117,17,0,0,0, + 95,99,97,108,99,95,95,95,112,97,99,107,97,103,101,95, + 95,117,10,0,0,0,95,95,105,109,112,111,114,116,95,95, + 117,6,0,0,0,95,115,101,116,117,112,117,8,0,0,0, + 95,105,110,115,116,97,108,108,40,0,0,0,0,40,0,0, + 0,0,40,0,0,0,0,117,29,0,0,0,60,102,114,111, + 122,101,110,32,105,109,112,111,114,116,108,105,98,46,95,98, + 111,111,116,115,116,114,97,112,62,117,8,0,0,0,60,109, + 111,100,117,108,101,62,8,0,0,0,115,104,0,0,0,6, + 14,6,3,12,13,12,16,12,15,12,6,12,10,12,10,12, + 6,12,7,12,9,12,13,12,21,12,8,15,3,12,11,12, + 8,12,13,12,11,12,32,12,16,12,11,12,11,12,8,19, + 53,19,47,19,77,22,114,19,22,25,38,25,24,19,45,19, + 68,19,77,19,8,19,9,19,11,12,10,6,2,22,21,19, + 13,12,9,12,15,12,17,15,2,6,2,12,41,18,25,12, + 23,12,15,24,34,12,45, }; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 15 23:56:19 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Apr 2012 23:56:19 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Simplify_?= =?utf8?q?imp=2Ereload=28=29_by_relying_on_a_module=27s?= Message-ID: http://hg.python.org/cpython/rev/4dce3afc392c changeset: 76333:4dce3afc392c user: Brett Cannon date: Sun Apr 15 17:56:09 2012 -0400 summary: Issue #13959: Simplify imp.reload() by relying on a module's __loader__. Since import now sets __loader__ on all modules it creates and imp.reload() already relied on the attribute for modules that import didn't create, the only potential compatibility issue is if people were deleting the attribute on modules and expecting imp.reload() to continue to work. files: Misc/NEWS | 3 ++ Python/import.c | 46 ++++++++---------------------------- 2 files changed, 14 insertions(+), 35 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Library ------- +- Issue #13959: Make imp.reload() always use a module's __loader__ to perform + the reload. + - Issue #13959: Add imp.py and rename the built-in module to _imp, allowing for re-implementing parts of the module in pure Python. diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -153,7 +153,6 @@ }; static PyObject *initstr = NULL; -_Py_IDENTIFIER(__path__); /* Initialize things */ @@ -3106,12 +3105,12 @@ PyInterpreterState *interp = PyThreadState_Get()->interp; PyObject *modules_reloading = interp->modules_reloading; PyObject *modules = PyImport_GetModuleDict(); - PyObject *path_list = NULL, *loader = NULL, *existing_m = NULL; - PyObject *name, *bufobj, *subname; + PyObject *loader = NULL, *existing_m = NULL; + PyObject *name; Py_ssize_t subname_start; - struct filedescr *fdp; - FILE *fp = NULL; PyObject *newm = NULL; + _Py_IDENTIFIER(__loader__); + _Py_IDENTIFIER(load_module); if (modules_reloading == NULL) { Py_FatalError("PyImport_ReloadModule: " @@ -3149,51 +3148,28 @@ subname_start = PyUnicode_FindChar(name, '.', 0, PyUnicode_GET_LENGTH(name), -1); - if (subname_start == -1) { - Py_INCREF(name); - subname = name; - } - else { + if (subname_start != -1) { PyObject *parentname, *parent; - Py_ssize_t len; parentname = PyUnicode_Substring(name, 0, subname_start); if (parentname == NULL) { goto error; } parent = PyDict_GetItem(modules, parentname); + Py_XDECREF(parent); if (parent == NULL) { PyErr_Format(PyExc_ImportError, "reload(): parent %R not in sys.modules", parentname); - Py_DECREF(parentname); goto error; } - Py_DECREF(parentname); - path_list = _PyObject_GetAttrId(parent, &PyId___path__); - if (path_list == NULL) - PyErr_Clear(); - subname_start++; - len = PyUnicode_GET_LENGTH(name) - (subname_start + 1); - subname = PyUnicode_Substring(name, subname_start, len); } - if (subname == NULL) - goto error; - fdp = find_module(name, subname, path_list, - &bufobj, &fp, &loader); - Py_DECREF(subname); - Py_XDECREF(path_list); - - if (fdp == NULL) { - Py_XDECREF(loader); + + loader = _PyObject_GetAttrId(m, &PyId___loader__); + if (loader == NULL) { goto error; } - - newm = load_module(name, fp, bufobj, fdp->type, loader); - Py_XDECREF(bufobj); - Py_XDECREF(loader); - - if (fp) - fclose(fp); + newm = _PyObject_CallMethodId(loader, &PyId_load_module, "O", name); + Py_DECREF(loader); if (newm == NULL) { /* load_module probably removed name from modules because of * the error. Put back the original module object. We're -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 00:17:04 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 16 Apr 2012 00:17:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314386=3A_Expose_th?= =?utf8?q?e_dict=5Fproxy_internal_type_as_types=2EMappingProxyType?= Message-ID: http://hg.python.org/cpython/rev/c3a0197256ee changeset: 76334:c3a0197256ee user: Victor Stinner date: Mon Apr 16 00:16:30 2012 +0200 summary: Issue #14386: Expose the dict_proxy internal type as types.MappingProxyType files: Doc/c-api/dict.rst | 8 +- Doc/library/stdtypes.rst | 16 +- Doc/library/types.rst | 52 +++++++ Doc/whatsnew/3.3.rst | 7 + Lib/test/test_descr.py | 4 +- Lib/test/test_types.py | 184 ++++++++++++++++++++++++++- Lib/types.py | 1 + Misc/NEWS | 2 + Objects/descrobject.c | 170 ++++++++++++++++-------- 9 files changed, 369 insertions(+), 75 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -36,11 +36,11 @@ Return a new empty dictionary, or *NULL* on failure. -.. c:function:: PyObject* PyDictProxy_New(PyObject *dict) +.. c:function:: PyObject* PyDictProxy_New(PyObject *mapping) - Return a proxy object for a mapping which enforces read-only behavior. - This is normally used to create a proxy to prevent modification of the - dictionary for non-dynamic class types. + Return a :class:`types.MappingProxyType` object for a mapping which + enforces read-only behavior. This is normally used to create a view to + prevent modification of the dictionary for non-dynamic class types. .. c:function:: void PyDict_Clear(PyObject *p) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2258,13 +2258,13 @@ .. method:: items() - Return a new view of the dictionary's items (``(key, value)`` pairs). See - below for documentation of view objects. + Return a new view of the dictionary's items (``(key, value)`` pairs). + See the :ref:`documentation of view objects `. .. method:: keys() - Return a new view of the dictionary's keys. See below for documentation of - view objects. + Return a new view of the dictionary's keys. See the :ref:`documentation + of view objects `. .. method:: pop(key[, default]) @@ -2298,8 +2298,12 @@ .. method:: values() - Return a new view of the dictionary's values. See below for documentation of - view objects. + Return a new view of the dictionary's values. See the + :ref:`documentation of view objects `. + +.. seealso:: + :class:`types.MappingProxyType` can be used to create a read-only view + of a :class:`dict`. .. _dict-views: diff --git a/Doc/library/types.rst b/Doc/library/types.rst --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -85,3 +85,55 @@ In other implementations of Python, this type may be identical to ``GetSetDescriptorType``. + +.. class:: MappingProxyType(mapping) + + Read-only proxy of a mapping. It provides a dynamic view on the mapping's + entries, which means that when the mapping changes, the view reflects these + changes. + + .. versionadded:: 3.3 + + .. describe:: key in proxy + + Return ``True`` if the underlying mapping has a key *key*, else + ``False``. + + .. describe:: proxy[key] + + Return the item of the underlying mapping with key *key*. Raises a + :exc:`KeyError` if *key* is not in the underlying mapping. + + .. describe:: iter(proxy) + + Return an iterator over the keys of the underlying mapping. This is a + shortcut for ``iter(proxy.keys())``. + + .. describe:: len(proxy) + + Return the number of items in the underlying mapping. + + .. method:: copy() + + Return a shallow copy of the underlying mapping. + + .. method:: get(key[, default]) + + Return the value for *key* if *key* is in the underlying mapping, else + *default*. If *default* is not given, it defaults to ``None``, so that + this method never raises a :exc:`KeyError`. + + .. method:: items() + + Return a new view of the underlying mapping's items (``(key, value)`` + pairs). + + .. method:: keys() + + Return a new view of the underlying mapping's keys. + + .. method:: values() + + Return a new view of the underlying mapping's values. + + diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1068,6 +1068,13 @@ (Contributed by Victor Stinner in :issue:`10278`) +types +----- + +Add a new :class:`types.MappingProxyType` class: Read-only proxy of a mapping. +(:issue:`14386`) + + urllib ------ diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4574,11 +4574,11 @@ self.assertEqual(type(C.__dict__), type(B.__dict__)) def test_repr(self): - # Testing dict_proxy.__repr__. + # Testing mappingproxy.__repr__. # We can't blindly compare with the repr of another dict as ordering # of keys and values is arbitrary and may differ. r = repr(self.C.__dict__) - self.assertTrue(r.startswith('dict_proxy('), r) + self.assertTrue(r.startswith('mappingproxy('), r) self.assertTrue(r.endswith(')'), r) for k, v in self.C.__dict__.items(): self.assertIn('{!r}: {!r}'.format(k, v), r) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1,9 +1,11 @@ # Python test set -- part 6, built-in types from test.support import run_unittest, run_with_locale +import collections +import locale +import sys +import types import unittest -import sys -import locale class TypesTests(unittest.TestCase): @@ -569,8 +571,184 @@ self.assertGreater(tuple.__itemsize__, 0) +class MappingProxyTests(unittest.TestCase): + mappingproxy = types.MappingProxyType + + def test_constructor(self): + class userdict(dict): + pass + + mapping = {'x': 1, 'y': 2} + self.assertEqual(self.mappingproxy(mapping), mapping) + mapping = userdict(x=1, y=2) + self.assertEqual(self.mappingproxy(mapping), mapping) + mapping = collections.ChainMap({'x': 1}, {'y': 2}) + self.assertEqual(self.mappingproxy(mapping), mapping) + + self.assertRaises(TypeError, self.mappingproxy, 10) + self.assertRaises(TypeError, self.mappingproxy, ("a", "tuple")) + self.assertRaises(TypeError, self.mappingproxy, ["a", "list"]) + + def test_methods(self): + attrs = set(dir(self.mappingproxy({}))) - set(dir(object())) + self.assertEqual(attrs, { + '__contains__', + '__getitem__', + '__iter__', + '__len__', + 'copy', + 'get', + 'items', + 'keys', + 'values', + }) + + def test_get(self): + view = self.mappingproxy({'a': 'A', 'b': 'B'}) + self.assertEqual(view['a'], 'A') + self.assertEqual(view['b'], 'B') + self.assertRaises(KeyError, view.__getitem__, 'xxx') + self.assertEqual(view.get('a'), 'A') + self.assertIsNone(view.get('xxx')) + self.assertEqual(view.get('xxx', 42), 42) + + def test_missing(self): + class dictmissing(dict): + def __missing__(self, key): + return "missing=%s" % key + + view = self.mappingproxy(dictmissing(x=1)) + self.assertEqual(view['x'], 1) + self.assertEqual(view['y'], 'missing=y') + self.assertEqual(view.get('x'), 1) + self.assertEqual(view.get('y'), None) + self.assertEqual(view.get('y', 42), 42) + self.assertTrue('x' in view) + self.assertFalse('y' in view) + + def test_customdict(self): + class customdict(dict): + def __contains__(self, key): + if key == 'magic': + return True + else: + return dict.__contains__(self, key) + + def __iter__(self): + return iter(('iter',)) + + def __len__(self): + return 500 + + def copy(self): + return 'copy' + + def keys(self): + return 'keys' + + def items(self): + return 'items' + + def values(self): + return 'values' + + def __getitem__(self, key): + return "getitem=%s" % dict.__getitem__(self, key) + + def get(self, key, default=None): + return "get=%s" % dict.get(self, key, 'default=%r' % default) + + custom = customdict({'key': 'value'}) + view = self.mappingproxy(custom) + self.assertTrue('key' in view) + self.assertTrue('magic' in view) + self.assertFalse('xxx' in view) + self.assertEqual(view['key'], 'getitem=value') + self.assertRaises(KeyError, view.__getitem__, 'xxx') + self.assertEqual(tuple(view), ('iter',)) + self.assertEqual(len(view), 500) + self.assertEqual(view.copy(), 'copy') + self.assertEqual(view.get('key'), 'get=value') + self.assertEqual(view.get('xxx'), 'get=default=None') + self.assertEqual(view.items(), 'items') + self.assertEqual(view.keys(), 'keys') + self.assertEqual(view.values(), 'values') + + def test_chainmap(self): + d1 = {'x': 1} + d2 = {'y': 2} + mapping = collections.ChainMap(d1, d2) + view = self.mappingproxy(mapping) + self.assertTrue('x' in view) + self.assertTrue('y' in view) + self.assertFalse('z' in view) + self.assertEqual(view['x'], 1) + self.assertEqual(view['y'], 2) + self.assertRaises(KeyError, view.__getitem__, 'z') + self.assertEqual(tuple(sorted(view)), ('x', 'y')) + self.assertEqual(len(view), 2) + copy = view.copy() + self.assertIsNot(copy, mapping) + self.assertIsInstance(copy, collections.ChainMap) + self.assertEqual(copy, mapping) + self.assertEqual(view.get('x'), 1) + self.assertEqual(view.get('y'), 2) + self.assertIsNone(view.get('z')) + self.assertEqual(tuple(sorted(view.items())), (('x', 1), ('y', 2))) + self.assertEqual(tuple(sorted(view.keys())), ('x', 'y')) + self.assertEqual(tuple(sorted(view.values())), (1, 2)) + + def test_contains(self): + view = self.mappingproxy(dict.fromkeys('abc')) + self.assertTrue('a' in view) + self.assertTrue('b' in view) + self.assertTrue('c' in view) + self.assertFalse('xxx' in view) + + def test_views(self): + mapping = {} + view = self.mappingproxy(mapping) + keys = view.keys() + values = view.values() + items = view.items() + self.assertEqual(list(keys), []) + self.assertEqual(list(values), []) + self.assertEqual(list(items), []) + mapping['key'] = 'value' + self.assertEqual(list(keys), ['key']) + self.assertEqual(list(values), ['value']) + self.assertEqual(list(items), [('key', 'value')]) + + def test_len(self): + for expected in range(6): + data = dict.fromkeys('abcde'[:expected]) + self.assertEqual(len(data), expected) + view = self.mappingproxy(data) + self.assertEqual(len(view), expected) + + def test_iterators(self): + keys = ('x', 'y') + values = (1, 2) + items = tuple(zip(keys, values)) + view = self.mappingproxy(dict(items)) + self.assertEqual(set(view), set(keys)) + self.assertEqual(set(view.keys()), set(keys)) + self.assertEqual(set(view.values()), set(values)) + self.assertEqual(set(view.items()), set(items)) + + def test_copy(self): + original = {'key1': 27, 'key2': 51, 'key3': 93} + view = self.mappingproxy(original) + copy = view.copy() + self.assertEqual(type(copy), dict) + self.assertEqual(copy, original) + original['key1'] = 70 + self.assertEqual(view['key1'], 70) + self.assertEqual(copy['key1'], 27) + + def test_main(): - run_unittest(TypesTests) + run_unittest(TypesTests, MappingProxyTests) if __name__ == '__main__': test_main() diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -12,6 +12,7 @@ FunctionType = type(_f) LambdaType = type(lambda: None) # Same as FunctionType CodeType = type(_f.__code__) +MappingProxyType = type(type.__dict__) def _g(): yield 1 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,8 @@ Library ------- +- Issue #14386: Expose the dict_proxy internal type as types.MappingProxyType. + - Issue #13959: Make imp.reload() always use a module's __loader__ to perform the reload. diff --git a/Objects/descrobject.c b/Objects/descrobject.c --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -698,41 +698,44 @@ } -/* --- Readonly proxy for dictionaries (actually any mapping) --- */ +/* --- mappingproxy: read-only proxy for mappings --- */ /* This has no reason to be in this file except that adding new files is a bit of a pain */ typedef struct { PyObject_HEAD - PyObject *dict; -} proxyobject; + PyObject *mapping; +} mappingproxyobject; static Py_ssize_t -proxy_len(proxyobject *pp) +mappingproxy_len(mappingproxyobject *pp) { - return PyObject_Size(pp->dict); + return PyObject_Size(pp->mapping); } static PyObject * -proxy_getitem(proxyobject *pp, PyObject *key) +mappingproxy_getitem(mappingproxyobject *pp, PyObject *key) { - return PyObject_GetItem(pp->dict, key); + return PyObject_GetItem(pp->mapping, key); } -static PyMappingMethods proxy_as_mapping = { - (lenfunc)proxy_len, /* mp_length */ - (binaryfunc)proxy_getitem, /* mp_subscript */ +static PyMappingMethods mappingproxy_as_mapping = { + (lenfunc)mappingproxy_len, /* mp_length */ + (binaryfunc)mappingproxy_getitem, /* mp_subscript */ 0, /* mp_ass_subscript */ }; static int -proxy_contains(proxyobject *pp, PyObject *key) +mappingproxy_contains(mappingproxyobject *pp, PyObject *key) { - return PyDict_Contains(pp->dict, key); + if (PyDict_CheckExact(pp->mapping)) + return PyDict_Contains(pp->mapping, key); + else + return PySequence_Contains(pp->mapping, key); } -static PySequenceMethods proxy_as_sequence = { +static PySequenceMethods mappingproxy_as_sequence = { 0, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ @@ -740,152 +743,199 @@ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)proxy_contains, /* sq_contains */ + (objobjproc)mappingproxy_contains, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ }; static PyObject * -proxy_get(proxyobject *pp, PyObject *args) +mappingproxy_get(mappingproxyobject *pp, PyObject *args) { PyObject *key, *def = Py_None; _Py_IDENTIFIER(get); if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) return NULL; - return _PyObject_CallMethodId(pp->dict, &PyId_get, "(OO)", key, def); + return _PyObject_CallMethodId(pp->mapping, &PyId_get, "(OO)", key, def); } static PyObject * -proxy_keys(proxyobject *pp) +mappingproxy_keys(mappingproxyobject *pp) { _Py_IDENTIFIER(keys); - return _PyObject_CallMethodId(pp->dict, &PyId_keys, NULL); + return _PyObject_CallMethodId(pp->mapping, &PyId_keys, NULL); } static PyObject * -proxy_values(proxyobject *pp) +mappingproxy_values(mappingproxyobject *pp) { _Py_IDENTIFIER(values); - return _PyObject_CallMethodId(pp->dict, &PyId_values, NULL); + return _PyObject_CallMethodId(pp->mapping, &PyId_values, NULL); } static PyObject * -proxy_items(proxyobject *pp) +mappingproxy_items(mappingproxyobject *pp) { _Py_IDENTIFIER(items); - return _PyObject_CallMethodId(pp->dict, &PyId_items, NULL); + return _PyObject_CallMethodId(pp->mapping, &PyId_items, NULL); } static PyObject * -proxy_copy(proxyobject *pp) +mappingproxy_copy(mappingproxyobject *pp) { _Py_IDENTIFIER(copy); - return _PyObject_CallMethodId(pp->dict, &PyId_copy, NULL); + return _PyObject_CallMethodId(pp->mapping, &PyId_copy, NULL); } -static PyMethodDef proxy_methods[] = { - {"get", (PyCFunction)proxy_get, METH_VARARGS, +/* WARNING: mappingproxy methods must not give access + to the underlying mapping */ + +static PyMethodDef mappingproxy_methods[] = { + {"get", (PyCFunction)mappingproxy_get, METH_VARARGS, PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d." - " d defaults to None.")}, - {"keys", (PyCFunction)proxy_keys, METH_NOARGS, + " d defaults to None.")}, + {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS, PyDoc_STR("D.keys() -> list of D's keys")}, - {"values", (PyCFunction)proxy_values, METH_NOARGS, + {"values", (PyCFunction)mappingproxy_values, METH_NOARGS, PyDoc_STR("D.values() -> list of D's values")}, - {"items", (PyCFunction)proxy_items, METH_NOARGS, + {"items", (PyCFunction)mappingproxy_items, METH_NOARGS, PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")}, - {"copy", (PyCFunction)proxy_copy, METH_NOARGS, + {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS, PyDoc_STR("D.copy() -> a shallow copy of D")}, {0} }; static void -proxy_dealloc(proxyobject *pp) +mappingproxy_dealloc(mappingproxyobject *pp) { _PyObject_GC_UNTRACK(pp); - Py_DECREF(pp->dict); + Py_DECREF(pp->mapping); PyObject_GC_Del(pp); } static PyObject * -proxy_getiter(proxyobject *pp) +mappingproxy_getiter(mappingproxyobject *pp) { - return PyObject_GetIter(pp->dict); + return PyObject_GetIter(pp->mapping); } static PyObject * -proxy_str(proxyobject *pp) +mappingproxy_str(mappingproxyobject *pp) { - return PyObject_Str(pp->dict); + return PyObject_Str(pp->mapping); } static PyObject * -proxy_repr(proxyobject *pp) +mappingproxy_repr(mappingproxyobject *pp) { - return PyUnicode_FromFormat("dict_proxy(%R)", pp->dict); + return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping); } static int -proxy_traverse(PyObject *self, visitproc visit, void *arg) +mappingproxy_traverse(PyObject *self, visitproc visit, void *arg) { - proxyobject *pp = (proxyobject *)self; - Py_VISIT(pp->dict); + mappingproxyobject *pp = (mappingproxyobject *)self; + Py_VISIT(pp->mapping); return 0; } static PyObject * -proxy_richcompare(proxyobject *v, PyObject *w, int op) +mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op) { - return PyObject_RichCompare(v->dict, w, op); + return PyObject_RichCompare(v->mapping, w, op); +} + +static int +mappingproxy_check_mapping(PyObject *mapping) +{ + if (!PyMapping_Check(mapping) + || PyList_Check(mapping) + || PyTuple_Check(mapping)) { + PyErr_Format(PyExc_TypeError, + "mappingproxy() argument must be a mapping, not %s", + Py_TYPE(mapping)->tp_name); + return -1; + } + return 0; +} + +static PyObject* +mappingproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mapping", NULL}; + PyObject *mapping; + mappingproxyobject *mappingproxy; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:mappingproxy", + kwlist, &mapping)) + return NULL; + + if (mappingproxy_check_mapping(mapping) == -1) + return NULL; + + mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type); + if (mappingproxy == NULL) + return NULL; + Py_INCREF(mapping); + mappingproxy->mapping = mapping; + _PyObject_GC_TRACK(mappingproxy); + return (PyObject *)mappingproxy; } PyTypeObject PyDictProxy_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict_proxy", /* tp_name */ - sizeof(proxyobject), /* tp_basicsize */ + "mappingproxy", /* tp_name */ + sizeof(mappingproxyobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)proxy_dealloc, /* tp_dealloc */ + (destructor)mappingproxy_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - (reprfunc)proxy_repr, /* tp_repr */ + (reprfunc)mappingproxy_repr, /* tp_repr */ 0, /* tp_as_number */ - &proxy_as_sequence, /* tp_as_sequence */ - &proxy_as_mapping, /* tp_as_mapping */ + &mappingproxy_as_sequence, /* tp_as_sequence */ + &mappingproxy_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ - (reprfunc)proxy_str, /* tp_str */ + (reprfunc)mappingproxy_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - proxy_traverse, /* tp_traverse */ + mappingproxy_traverse, /* tp_traverse */ 0, /* tp_clear */ - (richcmpfunc)proxy_richcompare, /* tp_richcompare */ + (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - (getiterfunc)proxy_getiter, /* tp_iter */ + (getiterfunc)mappingproxy_getiter, /* tp_iter */ 0, /* tp_iternext */ - proxy_methods, /* tp_methods */ + mappingproxy_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 */ + mappingproxy_new, /* tp_new */ }; PyObject * -PyDictProxy_New(PyObject *dict) +PyDictProxy_New(PyObject *mapping) { - proxyobject *pp; + mappingproxyobject *pp; - pp = PyObject_GC_New(proxyobject, &PyDictProxy_Type); + if (mappingproxy_check_mapping(mapping) == -1) + return NULL; + + pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type); if (pp != NULL) { - Py_INCREF(dict); - pp->dict = dict; + Py_INCREF(mapping); + pp->mapping = mapping; _PyObject_GC_TRACK(pp); } return (PyObject *)pp; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 01:06:16 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 16 Apr 2012 01:06:16 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_416=3A_Mention_the_new_typ?= =?utf8?q?es=2EMappingProxyType_added_to_Python_3=2E3?= Message-ID: http://hg.python.org/peps/rev/0d9de3bd018c changeset: 4253:0d9de3bd018c user: Victor Stinner date: Mon Apr 16 01:05:52 2012 +0200 summary: PEP 416: Mention the new types.MappingProxyType added to Python 3.3 files: pep-0416.txt | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/pep-0416.txt b/pep-0416.txt --- a/pep-0416.txt +++ b/pep-0416.txt @@ -36,6 +36,9 @@ built-in type sounds good to me. (It would need to be changed to allow calling the constructor.) GvR. +**Update** (2012-04-15): A new ``MappingProxyType`` type was added to the types +module of Python 3.3. + Abstract ======== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 16 01:06:46 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 16 Apr 2012 01:06:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Try_to_get_hg_to_treat_impo?= =?utf8?q?rtlib=2Eh_as_binary=2E?= Message-ID: http://hg.python.org/cpython/rev/c3b823e8dcd3 changeset: 76335:c3b823e8dcd3 parent: 76333:4dce3afc392c user: Brett Cannon date: Sun Apr 15 19:05:31 2012 -0400 summary: Try to get hg to treat importlib.h as binary. files: Python/freeze_importlib.py | 1 + Python/importlib.h | Bin 2 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Python/freeze_importlib.py b/Python/freeze_importlib.py --- a/Python/freeze_importlib.py +++ b/Python/freeze_importlib.py @@ -24,6 +24,7 @@ lines.append('};\n') with open(output_path, 'w') as output_file: output_file.write('\n'.join(lines)) + output_file.write('\u0000') if __name__ == '__main__': diff --git a/Python/importlib.h b/Python/importlib.h index 698023188bbb2d39cb1752e31d750cfd46c908f2..f11dcbb131c5f7b77075b5d4c0523e52f33a1c6b GIT binary patch literal 169401 zc%1FM+pax7avqjzJ;hubow(WOMv#jK z^FRHEfB5@<{lEX?-~HYH{da%+AOFw)^bh~|Pyfe%{CEG|fBNS?{HuTcH~;zX|F8e} z at BjYufg=;!|YTo-PX8!YtQK|fFX%t{|$JeKE=+djju zPduoUWH|cN&R=qmX$^+M!$|T{H|Uc;KX63J4g2D!+_Mpf43vxl?>i9b1bF%q?*=jClY*~M+pXLVp$E6-D`T9mVGl+zPZsaOsbnazedC2L2vSl z+osR9QG+v;2Y3P-P5?f54kR_XX?M9PPinh;(_1FLmIHkgJy6q~pWJn#uw3-1Hoc%J zufV=)C))MS1Xc*<^Ny9?A%}!tB%EV+!{2x4zA!VQEN;q+w);ifmFPcXAZkoZv?;Tb zo2ZjtcHz$Nel5!f=4Cvy+=$<}=o=4idnEU=!iL=H<}<)eg=JRs1)plu4VrGI6Thg( z?wan}w6x$wJ^Z2`r)zpRB0iWB55IcHElrh(SD?g`pFI6qohcw$ioo>YnrO1$F5?A1l~N~+lh^R(e>JC7x?EoRinB$9M#Q7g{HmpF5J8z_Zf|fcj4yw-)=ki z9e1&;&S$5#=lAl^=eLji{Ct-39|y_O^bz{$BcU at DE_p6#zCRy5zh6acKYu?z)ANqw z8RGNfc@$oe`BMJ%)1iM8ck*erJuRRAT^p~D=r>?my}X at ZKm$atl(A_^*&{Z zQ(?)u8878VBhsznGi>&YJALI!n~cA#+BvPlZDAOn&ky?iX2O4tQa7 at VyMNly~P!#uT>Yxf>Ly$tklT7jl4>wO%WaB||DC=B0M)|m}=G7am|7nSsm=XWU z#FaOUR+B|0P|qp6*Yam(@kwc8K9LtQV=qT(+ksy8Ng3#lQjPf$v)dxpHsb$00 zYb`~e;a8<)vBFh3j8$$}vKJ2XS%rIV$wd;0)P8x)q_TB~B7 at jR*-s1-h&lWfT>VV&jBp^ z7v}&J%Se5FKL^UgLs`7p-KzGtN3tzc#Jy at 3%l at T=?qJmqDQt&nfrV?E?RsUqU(I5UskOwCrs09{uu>}Y1JrN&s+H~R6a=C5zT6Gu)*hV zRmVOL7fppU7H&+8_1NS+grWCZJYzmqYOKx}8A-RX;5PDxZeu^&xt#7+V>y@$b<2pQ ziVtR=y1BxHj&ou?-s<=VnGv7=?&$%43a2UD4$MHba%WP==_M9EFjh+WoKFZz3>pT3 z3uLYd+QFhm{&!vUzvp)*M|%i~SBbeGHWd%J&>G1<;cWZFIKlHJtCXyXUb1VC|$R)DeP zunpcIrX=Q)_XW^K(xoiRxFptMfDfI@!=7Nt3 z6XkDLd=hx6vFMzU<~f;a&mkxC%<%W?riSHg!lnJD?-;O>bQS>mkp`;&so#DB_2Ju_ zD4tU;Ph&mF-p0VzEI%zi2j=;QCyM at M6fG35>O+4%xp-5=>bh?|gaF~o3Gv7>$-E=K zL##GB@(eo{YI`=6wHCKNOr+*?DCf%@U;dyu-z$0fIUvHY;AedJ_k76e8mBNnyxXUB zFErL99cFExnXRh`lQctz)WMZyWLgC>on=pW1mm4Q|@6lS~fsRK6itHaql`(;Wr26B%UgWRD1K7o8JgZEp8Y6!i&aS&rh$w&vr}|1fpepXhnPxs3a}Z!6#UpUPlf z&C}BQULx}3eBN+A at o4If0xX!1T6IbxniWs!+Bl_ILWqWO<=z(RU80hw0>_Cyb1E;W zbwcqVvjv7cHXlm$w4mc2(KPGJSJ0t+WrKXG2Ky9*QGl2zOW at u0-1;EHrMzJ~$jT}c z-sEHkOab_TXq>N1LHGeU5MG#q;|C&UPv6g8%}}-qxNU<$SRpU$T;F9(Ks&V?d}A{p zPBEBe_)W1rx)T45-<0z^24*3 at F(_5z{1>VVR`y0k0tn~|SP^p})(387MM;P9#`=0g z at uSGPgJVvpK!AtBXkj~qN-$fBATo|Dtv$IY%dHYQY9WFwmt)ls=xm-?kFY(%X}OpH zjeD(La>H}JUUCLcu#>(l{>4a$m&Kx&)T`rH|HcEbSR(8SdaGqOULNVh&_(EZTTKj+ z(DO4qjRgYvOC+2$RbtM|&8LEWQhF-*K(JV?PX&+GX}G+uU!4j#5Po0GsbIZj(-T3t zR!pn4=cLkbO{$ifnMZ*+?@2=6{?sgNb6Y#2+cMlRcAlQ21T5-Dx-Fck?s-bp>a at 5G z?%OjkrDL-d4}BfQ%bi+Xv^D^{5LH(H8PWjvfsTaqZKjHa6EHwzAlCKy@?M|JC26p` zL!_GT0__AVOzRXJIXH^kN|8JRuRSK{BXF}hTGoXzH8pYt{G1JFiV8237u>fJO;@=q3xxKnAAX#WD{XF`72 zm!ejUF3XFCEo1wchHc31dkwoZH-3*AYxG-`pedUcx>guPgE2q6G&i%v%wqDgwfk4Y zKORKTzbGJ1xpv50WcdR#@2Mcl!axr(Du at O4z}I7Vs`_vUGsroM8?d6OnD&Ahlx(B& z4>)syi;(exE`rRl9P4rMv8P6396KCyI>JG|NCTp< zK%0RC`k|C!7Wa_1rkg?7!#mRH4XrODXlO})=4OC}t+c at nwzHZ#>xM*kWfgn^kHLP9 z$;=ZJLyLUok2c|zBO`Hx(1tXUKz+1cSRSa2g}hX5&!Fnf4su|hsdrYerngL>OtLyS zAL2^Y&w)#B?%`|~9p)oRGJQT5r+K3H?({QJp7p2Ui5*;-jaSdDanP zIsi`cwXl=5m1L9jeWD!bhcjyj8hNs2=J9+?zp9XVlo%moMUL)=0T-PjRVJuv4?xZw z#CE`&gg5P?Q8W}1i!D%^_BC&&O8suyoEie#EnNK3dZI+!{)Q8o&Q1rB at 5((gtaox1NHa1R~gAK)QElkj{t!-)> z>DDQOOhuNv7sqh`u~)>f2r+064oEk8+ONdb3>}v}0RWkFlzoc%YFc$V`-CF1=rLIe zuUFQiR*Fo1>^})2C~B2evILJa77L7TXlSHYRW2Nf{^O-L>4Jo=GQZ*KCocR?FcPUL zG!=fDGcpQ>RJ4%Y#;>u4;jy}fPY}Da)rMuw%_w93EzYSVn%0y-yYf={<+&bYDr6d^XAzalAC(*`fyAV(OjX;SZgBI&aclVl zh*(4>sOiB{DFehTCM5aRJ{DLSMP&|st1QahTj+0fi(`WB&QGN^dNxm(4q;qChbdcwwXN3d}_U>!pKm-KOA zZiN*nOF1>j?_&PFDQB<2; z)}xqOB{%)C&knU~>S#LvMmD7zMiR=ZI4FDtSDwoDSjensp0N9Q=Z{;)NwJEpO;Zn` z)i-Dq2XP_Xz=+AnD(q%NmuyvXU7AV|&sk?SzzW!9xuRR#y*d at ZaFiFz5_an=)kV3mD7eGXfet^=j7hhR%sU%va5^Q= zIxTZ5Yzg65ClGQ;_jj~oAs6UzJ2`N^!{ZXBE*+)V3KB`u1 at hBJQ;-i#T7&*n+Z#91wFQ+|On)8=CHlttLw<66p-KD>7cxS7qf z>KRdYOrE2EC5wHjsf;#1)6?^1&b at ZMuDW?3-RUXo1~}PI<_wQ_iYaDbs}(xMb|Yts zhQaZ5!p$PvmS`t3aK)txx}OUb>kWLv=_jFMVJBVNALazCfrtaV2Z(flSELtW?zp}M ztwr;_`_ILCDXW60_iJp=LIE4U*9B}M=^2?oDy5$Nj#sb{51E~IAhUJ_a%M55vl_d= zpA2QDQ^jy|R4^c9g)e2sg4eOjDJ1L8B%`oUhYCQ;s6axdBap3%`ZWb?lZiyAc_m(J$*N{oBwizWpu-8`b!-PfZ++VVFISyb(311NA at vXr z$jE{edfPntsA$bnbqA?B`)3EJ1NlCzC6?3jGL^A96|6m(S_b0~gPu%Pt5UuWYSLWD z-w%bYHNHpvtiFIBac^+P%oF-e49872Dr}x42nq6Rd<>QeqS;ykSjax|8OQYCyei;Q z2|Pn{YgI at uuzgzxwF`kmY*>o2TRNMKelp;mQdJbnbnV)b!OdL;O{+1GtJ3mH1tE0a zS9C;6`LcPsCVn|+7CwwHP~yJYgxrI#>4Ve;ggD;&QO061vPh6`XZ+bA-a3C0>cD}_Bm2q<5-)#4D zSK>h`l|!mWEL^%dp#5-j8cx+UUo%4eFEB`0Z%&7h at WhIgn zKBN5X<}fJnjH}jFzq(qrmyK6~G>ob!xg4~USA%c&fZ`@1+81j~ai>x at fA%L!=;!Ml zEDYRo?{65mJ2}XElCm=J=Gp6FLfQ2yE*z5*D?K1Da%ypX^%T|c0F zr~VFZrNMC?dG|R8Zd_(O2U^&PuZpx;8`8iy0obVD7AZzUj7m*KNj>Ayr?k9|DCvkO zoU_gskS(aH=T&80j1i&d*!w-3Jcu7w>jToY&{X&J7$n7qA7B-;2)(yJKNrpzK?Wiv z&?SH=WG=X`bbVUXX8>ZT&(#>jkU6wDFiE4;ill-9tJ=e}%v@~m>UKcBT}pY8?}N=VV4aKfL1IoJDMWN; z>9kfzf|N8RJTQer^S&Kp9%Oj4a%t}1G48-!+<_2xYdn0M5nSAV1m@?-3O{q2{<0`* zGv-l}nms~og{8S{a_ at v>52dq9fa{T~aB+V6_fzc4>GX4KS3Xdvx7Rr~{?0U2MWSpT zV@!NWGK2od$~Xv(htO`2AvTN$2o$Xpd}BwjX~kt*=HDCFFW1WKC|)?Yp$SFyRQk>8 zG2RFH2>y~qgTXzee*^kdg8&FT)Wp>X#rFvIrsQVxXLCRzWq{DP+wE*0upQ`dR_w*pVZ6O&kZm1yMge!cmXHE#Jy(t;#HX z9QEf=WmXVmQaRI8nH7zAjb^@9VV_}v+_qCkp-=|2QR|FPS)4dnD=8*A=LPZnF9lLW(6n)rJ-=LZj(Gb!`p0eyfhKni z=Wbv{LJJX0{$`9I@$49fuQ?8IfL>?8T11%NtM`i;ISc{KZ8r)amwy$$(Oha^n zx3J~bK!3qCE at ywOWQt?^zU)=VQz!BY`gZ;NgyxD4)K+|qW!hDISm&XIe^-21B9;cz zi{cX&LzOBeZ&0DZ*M=1z(0RPBIHveWa7!n}(5gJT{=mj6mB(m1La0X7 at eW=IZe}^q zQ+cem<587BWy^)w3QS|lLHB}$mk4fNC}Hbw z%FB#P^!@m%%an#S7wkkO=X+1_BB+P%)yWyTM_-(re0&Oln*yW5s}-Kf!Dw*Wo`Kvz zB72~@@5vrO`k(0S3e_H8FH}=xT|n2Usgwp*T^Z;W)aE{+Sv5uZ)r7i=Ra5NpzXgy# zY6 at r=adm09$g}~->{ac4n=B=+4-#INhz;>friuMNb*V^jx}B4+W6$eYfB*?&Q;j77 ze+YCPAi=nIH6-n|R&TWcLM3LCgFb_H2Y0BhT!PmqH8W7a^BpUW^C`9B4)=V*=QmDz zU-NVBK9w2D((wm8C2O=))j83+=a2M1|+=qsdXSYP6GP0Vv$XtN;VFSwg(jjdSWt)y(t^lo&ulg zC`T@&6*qsCAu+AgJz2Hu>@25)$Np7isgpIi)d z!@=zI!WmxZe;SDWna%8a;x`}kGdDOpZ+>2qHVsHqWt6=ZMtXdwv;DdYj!6j7W{xB}ruuxw-k<$wIQ;f3~6JdDsmPDG1YAd|dj z2YgFcyu2qYJR60{`fv+$F}15Z@{$}guIa6 at Uf~jr(smp#A1x>Tk3zd-Yaxb%zlz$qU9Y%qqx3GFClh+~RSJZe)ysV|GN<1Xd6aObaIymDF4z+v zdOJcS;Vh7txCZhx1?#tBu^|zIDH4oxjEvHx+ywBvY&-6o;eQwEYwGe4O++ISilxdo z7AAWa3JoHL=QYV`oPD#qpyeXaeB_jg7Enq}u z-8%zkJ*;*U(mLRd89s!!d#Eebq7V;c$!!{tWs$$IMKdc5knsLT1|E@;Gf(27orM;v zAZJa>fY-4KlS;BiS!}rnVRxJXF^^t_!-hWsME(z4Xdu!J955=<)gT)`VR*PebBs=y zaueyj{)xU2(-#8NaS zbybOzmT{HWJtw3B&80#x#tIST*N4QN4`9Z_irwb8+<=y*OyGxFnr_9AmZs+e%ZKmv z67%XlbZt%t&aXNmtiZBjH_m4(Z*dZDc(S<%$GRM8!Ww^h&P6_=N`6F{h zQoqOM6-jKea37K-QK5maX(S!kMP5rMXUN)aG-l^DbFc>Cm~{?Y#z}R#-Jc<%GBi>K z)%?Etg`!$!4SMH at B!blv^S^NxV2z`|^@_HmNTZu;jvAfpw_nNdy{^hcwbX)Mq5z(& zd>>?IrQk0~|0womwmCEDVu;(QThAC)WG}iD&D`ON(H!A$q87bI&e#Utu z%Xz0i0nC~sk7VeK6kRg#NY>6sq2 z3l}HyNJh at ca5&Yv=Z&pb3}?mqI1w|N8~#Y z)m9JNcZXR&Ce{x*;)0~k zeP^Ky64;c~3_%-Zag_WPA-~aGpom$3Td}ro7GvGiUd5r{^h&b=52CufxXTTD{4NeX zJQ{twzPfm0(5?q3Pt)C1X5>9xzg1VR!umjCY3du zTe1(b=1u38=sML2i=A6SPMmi8=G3g|80MhE`57``++RDKft244XN1Ry z^58(3rzas-g!qMRY52p>4XSZpm|+M_SYM>_h%YQZyz_J4!1^K#)BdFxbQsx>ykM~7 z-+95n8Xoh48SCT=DW}T9fEVm{C3lQskDE{LsN7)SOKA$?F&CIWt79%O*>5Y3Vo3z* zEQ+I+B=W4A>8m4&W>ByKvwiFcRjvjX(upukjs3C;KAz}O`ZL!f*XC#?bb5EPwdIbI z at z*Z2-)?UjavVYFbG{IWA3MSDe1)MU|KdOU7ysFy{|r)mNBw6lCZL?-d*@l8bq+bt zn%eQJ^X!Xb85K?V&UyCR%~x;|G#TX!Q at LhLkLx6A-~49w;`2X&FC+As0X=|g zPPK(o*dJbF@#-=&IW6KctJC$U3H!OgH)Ne&H~l#$@mw8B|MMjNqmzDK(m2`txZCE? zk$z+HNR5K at p(q>e&C7Wlnx;;tl%%+i9fWN5o(BcfYA|7!`9?VhQQRn7aG0;Aj*#ap zESegm%>DC8&RbGmp(;#j%$mJ2vh1tLxmt5|Yxh>>KnA(n#qod!Qru}=Ylu!!`GbEN zRd+XT2U~NwR&^~R!!R$D6ncK-GQQniQbE;~?s)&_j zhcy$eLa?gN6vdSTi={p=+I5XS0o^)vOpSQ7_yIldH`QGz-QOZ*EA;v|7R!h1k#Mz)Hz07WsX3naLxUa@us-EbU`FV at 50W{jQ+bR>!ByT{>UL-_1}|U0v_OhE2K3ny3YD_U;-JdtVOetHyt{O`-`uEkRRm4!y`b21Xt+ z*ioTrv7VNiUQ#FwJi-VRl4f{{l3`86)l_?^j6(KsJ+CCah1$=GFp|s)=SX*>ER9MG zti;Rz at M@yisj|zY1Q8}p$od{?FQJW>gk;A&LpE&U+gRgeRZLpfwz8K7Ctfr?^^)$O zjIyR|0)hmJz97>bh)Ogq3hs=FM;5I#e{M@$z}McWW7`O~qb>=-y~6>HFJ)s~!Z*r$ z#a at qTweb>L0e-%NagnM^JvmNbk at w2+WzHRV#vK0V24yW7oyO--JT>e2|4FAb{PgT2jM(~OH zjOe at tQ*Ml}<4du397 at RYVLCa<9Q_au^phO17y#lLkjdospT!J7tDfJs~1Bv zkg4V$g1AP=2)qVxktuvjEx}kG5|JzQUyV1| zvnZU=L_oGlPNv=yv*LfMc~Ei*(_Ntm6PYaKSS}vf#x14(O4NnJjs6$^dUP^o> zxeCx at LnjH*&A;W6L8WZA{%6mo3IA3e4!+1$g|c60E+LSK9X3n&B6&W4NqYG7_>}1R zm7iP^MRBh_K>s_;1>J5={T*H4O5QnCFm`JC;HuoCx(b+|@%c7v)kekKTF0MF6m!Yd zE;ipxU$T{?=A8f^dUZTMyi^an(9c^tSZGXV`Gw3X9?tH at h;M|Kse3GuEm<|fhdm6V z-<@tIY^*xdmhH{3r}+TuTr5tp+mb=VvW>gqa>`f|o6d`01qG6xo$(%+^s-GhC z#xeJ4!#QuR>$Kw}ZoF4K5C0l(nEJk>sB#Wa!xe5DC4IA;tFti+^!lK^g=UGug7XY6e-FcI4PKI2s}kv+=D>{?`LVa10uEL2_| zmHa42KWoa{o_T`wiL3a96{udN+58h{Ixe^gF}%fEs|#|JDbJ$7=W)#qhdTtmK**tW znnTDTxQ}*v=CIH3$6#DwWFge^m|Z0cHx`acOcF}A*tc9bn!F8>3yT+uO^ZN5i+Akj z1qMNe^DT$E?3y4_B#IfU0JnTJtj2Q#Zy~pWIOL!*1h`5_+kzM_qs>VmSK6@^_`;Ow zsXEPKsudJx at v=4F@!DWdbO!T6*(?4IaSrtK2lh+2i=!c3fvbZ4E&Attev{QDwCo zHtBoex*}ZV_{69R at -TZ8-&b865MttW8dotIqTs>JJys;_ z(s?JWKQ*LfDC{&YC5^5Ag$f~9|Bwn{M)rjY;n3ReRS3n?hE<40bkmZ-pjv|<9=F)| zx$jg6(URh!z$i?~H0V&=?~w-KP?fH!Qm04k at 1}|bx^zyX(Y|*E!}(K*&Jgrh*^*Za zwki at rCb@Z6PMld%3u+#Hv0uEZ- at eDlp3@;M-mo*LL%i~|nw`-bl&5uT)bL^>%1&

BhCoF9!Udk>Ga=sk#B^dkg8?#1(TLOb}6nAv;Q(zyFSv%gtHnj}Td% z%R&Z)=XV96D)W&t7X$3hNYm}mRgXGvAu__%s at fe2$?O`~<{+^7qQ;N~7KJSM+y|kY zd=|KxB)5uU7ZN8jK95l}dQM*`n^-_M5<|~=TzY+H2}hT(28YnqR$dZD?k;PRU~o*@ zNR;tFF#(dC07;&geSet at XTNY`#`73z++{u4(+>$c+(_aq;IdNql<`DPB#o{UtrJ0a zAO#UgMxrSH^5?3-M?kwb3b^HsE)Nv^X-fD4iz49<6(rc8f1&;>Kc$y2cB1*j{3;!- zQZ62poBvV4=0r at KT`20FvL*d(Yl#hWM)WqY*o`=4^)!=68p_ASiq`JLnY3 zq;VDDF8=;Iv%ni&@$HtIX<5ycCpt$~U>Augm{PfzJcpp>UmgjcJ(T59$@}Fa{ibaF zT;^o0%j|*EwpL*sr(vHd-waGu=|f-|v;$TtIDFG2)S99ZP6bo{Aw-b!7i!~TV&;<+ zIE7l9$-_0JEJ)kI9KuZrg{xAi>X!AW{Et!ybEg;FGRt~UOTnS(v{g)>3usi#BOL7I z$C)-&W24dL?A6P4eB&yydVJt$Aded6P=ZEjRQY{;7KPmrpHxNM4EDZStExxV8Yg>A zQmP)vbtmfP)y%oQG_wodWzP`1 at gc+Xa2*qEEI}4-O^Qo&q;-3lf at O$i%BBpFIQ~~+ zhdCRIUSxOL at 31cEVq(%4C?vk-xPIUi6_Y3egdf{lkCi8$z98Qh*caPTv!f~#Jx+zJ?5u*Raq*jYrw}tm_Vvu!SgOIFdy>2 at UHV02NH>+ ze~Ah)q%R$0-m#WNFTA7TyxPDpirnP74D}`#i(xW3)6IgeT}7yJq>P)8{6;m)zA_>x)vngTQe+#-a(n;()SNb#*{duxi*f2DvSSD+3r`eFg%zLtb!g{Jt6j zO=htocy}xny#ln*hX8)>WL%dR`KK;sTQD8*OW5Y(SHv9p75HQ+6P zzJe6+HWp@%STpsU{n-L$>|g|Ij5tPcOSZ{AVXczP6b&k9qqm7%s_=9Rc_59=NVp9~ zs3gyD9DtmVRUk)knK7>@4{!+a#C(4ME;eN7CQP5l$tR$^-B3aYV8iQc)Ur)ZDn$Ix z$!C=fJp!#(Ig0G(eJ^{y*cM at B`LODOt|W1HIapxhxQqu*XLq#)c%=Zz)(x~`n%K3R zH(*}gtJlKjZ5qv+4;0}{V6O(#3{vI!3 at G;&Fp-XHfL=CA9Mmvm^9>&V)Dau}vsr7T zB3C*Nv8UHCf{50H$@*41tg0KQ?y`yu4i;POECIBvVZ0{Fn at lq3XnNT1&j$J8B9~=5 z0GgHLikWX3EvaBTrGja#0KsU*cbski`nwgIG4MnWJ>Ne+PsuskO(xkv-#rM&!6|7_ z!(itJrN at FnWfS@0UUG_B{-P-4+(kOMm0-%?z;9vMoqD#lzUWD+br%#-Qtt*1h86 at K zjLQ<+yP)JS at khgTfmLT6x99^yxwBet>3wuoD1qxOd`2p?t;m~qm|`~89_>o)kFvFP z5+?-qzHV|u%`l!Vb~P7nhC>ax)tCMI5b*@f)pYKKasvx8OWrc6EgBKUh)TFvHMunk zj(wH{{YPq|jz?WVdkT at m#O2dZK!esX0|u-DG&MU*_sU)gTu?=1pSE*~AQwc1Uf`7> zJj=(CLGq+-bN2v3^5o+A$*7*>4sxX@#aY(U%@2weTUCC*-|57tFuv%sl=ieKs4oR)w3D0H5_)RsB4hTZXu9)(_ zJO6yZ&vI3+?fN_AFc+nD>p4%lRg&g*;8V{q522en*%|Vj^?cf7=kO{OaY4EJRFe4P z at k$la*ol>qk_m~-{ImFu<2+{a+q&WmDdB3|)eRrp{vZQiClLRVb_iyq4TpDq3InX2I6VhdV+r%IDLRbBPstlW zdXC^jiEd))CTN5vPkv4c%3`bqkqUpTUUdB~%HdF|D^|&_y;=-D+OQ74T^BFMDs7)% zXLZ~9o)OikegB4|UgmS*K++v*wxGzqB%k@~*Ff8VyaZfFUcp*-kX1I1_=G6DEZcdH z-Ze^ACIw|~_+a8ZEa~j`rXv`6&D*lG*6{h?ae{WK_hJyhaWkF)^1sPlD}J~gqUS|j z-#@-`SF;stNStC8M%~zXHQuYQ|M+lqz|oisl8A5zP~9E9Q`k9Z<%k_#fomV3=uGyF zGULgy=csLzaW^C9gpY_U#t#5a*o at ve`D2{4=UN$NvNS~&F5tuc>ezf2cF)SchXf_C z6~|`eHaU$u!9@=0W z_AuJ$FzitqhF`)SAonVH2YXPHcgvnU7C1Yyng?S5TGs8F>a8BXZxi4RVKcafV&Y*L zx83llKD65C at v2 zsw98|*IjBoOV>_p?HN2 at kM2)ewP0~w{uLNLI-c4bjGY`;tU(dwmq3bVa-bA6z;&Ui zHy%e-;A;Pi%n-(B5JEaec=9Fw!B&CW at v3pn#Ne=qbQm6RFO-B~suytD9Od)RE4`3Y z_47`Hoy6A!-khr!*E-O1f13w-W8?A5%@H~_&S&8~6_|j_*_v{`N3I8YmcU59%!Tuc?8}7@%|#|SgdEh72Exljvs_`cJ1ir_AQshS(2xVwYU)so z#OY%Yp0A;qPN6ScRIdY2uDZidR*0H4`wh3uJgZi-BggZu3#3Uxq|$NAlisGbfe8=r zB?K^%TSb_eHtl9(Ol40rmOiL;07Bbjxy)xZjpXZaOAR6)={#d&c zN=&I176V>bPAIxtrW?6K!@W%m$SdHbtxN>xJKz;`I8PPe^^yb?sil<(6OstSvi-mt z0G|ZMeF?nbHx)Jg`!G1iiN6km6U>C4wYqbM~?K)xYYjEuOg6x zM?ioobBcB698e`%)LsA^Rs-`R6;LI_N1wgK;ix^~<8UINiqD_BdjR5Y=oJT!B#ygT zKv;A_nXq_acHXvDSWg`wTpLT;4y+{hzYno#+&3nk9(BifPUr{S3I@`10 at GLFR^nEo zP<^2smVNG8Kp+zpFg{eD{c=nWT1p@}uNrI8Gj=jK_mbOcZ&|<@AYUTzsqLSr!Zcil zTj+^~12h`Z5e3k{suBzl{#ca|SmS$D!bY)uv7n0t9`eRQ4c+|c3i|G!<)99wVTi!K z6)eSnhx=KChD~7cQH*#Zi0kARZ!hXy4fU0qFl6<>fRSQbXZjZa1byu|jj at cKnVhZXQ23p9h8R!9+_K-(Y z^+~IRhI#84%fS7r)m2uyemV#+H^_K!qxgGzxajB#DHv7~riTN3!gvMX)xGp^LwGlF zW1k-Wr!nsh5>yswD6ii`K{RA&qlx9t%Bp=S-^t6$nbN6 at _;$OxP+f!MLR$4%yk!lE z1I;+QzqW7`e|VM~jF)ujRH(C^6H^NsAb)1_K3}4EO%QM>wMUwEm6z{@B1i0am^DIOT~YklJV}t}9xdc*k`INn z3SjLF_ at JtaHu&;Zh=H?f)ZAZtOn#L7v_*MvG{y2- at t(gP0cDRpJ-2fNUIts}03$yP zQuqb at B^`YWf6)|2^;HgcTa{ z8E=Wuv?Lj8jKJmRFDhtjuQfJ~xx`gr$rnDuc6jh`X>n!E##aSy0h% z#ESa;McQ42I>dIX;a0xd(HEo9VWswZEkpm*9HE(OCg#^387PvVgR5^rM^iS(lus_4 zl0e1zq*yNo9aHgLl;|$u=!XD^Nc^R6`YiYzfo}v!rbD at Nqmdx0NkXM4?7yyJE5=E_&`^hwZ;)0b zAbC$hxOZB`6<)kje6^!fV%e>%BwJdvcA>kNtbM}De+aa-gqBP;s4Xg?OA1Y*x(u-X zO#K2=mB1KasiM0&*r)}rA+Bbuo)}!)X5gw7I{O{)rBke7Ll(zbNNoCA?+Qs+zOX at V zMu+{ChIwG$$rO7|sQs$JEZL4-gI7wP)x$C_{zOZSuk5b^OSU5&KEjILiRsU*HPd}XqPJ7gMOO|ZGQ9HRIFmaZ$o1oJ~47wfU*YELmk== ztIF`v89OlsllKJK^4nZqB*7GoT$EZXBBt2MsMiJ%hwr>L>Qws9 zYhyYrhoF_E4*&@)=|GmgCg=-F=wtu&`0SIR3)TdvN23l{vhv~4ft>{iaK{_fRd0uN zE9zB8+V)|2_Z2mbpKlOgWg>z`B`oVj~JRTidmq91r{aNe}3M0pp_ at vl9q}U-ixtvex zkhY*L at C$sHIkx4ooQ=-IvX7NROxs`>I+&1hOs-i~=uL>n`7~so#a1{^J)daCg3m;6 zYY5&LIGO;Tqk3FX^_^w&UFB2GfnX`KqVldSd_x7{;b|qJ+x3nhQJ(T<)Rh&H3>790 zbjRl%N|1^vGyYQp#C$U;9?Q?cI&XOgXAy54Oe=}Oa0TXO5p*qAPZ_}(JT40Wluab^ zEXSc&U_P#~{5)mymInEQOJ8=C)yCsgrB54Q?p&wt=6@@=ulcYQf<`DaSx4$sM8^%H z!d;8Tg*OW`Qe_u3-G$R3JXzI*d!Ij`_Vun#4AI(a!TlT)x$sM7RBCaYw}$4*sB2hE zU0M?8HQU-FRWXse#(<*F^?LQE!%$e3AwAne{zo`2!}ie5mJ|sN|7QR0y+-kc51o2(OJW5oZTweSN<=DS`OiW~F`HqTydA-i8>1DmWp)6_ z!-*{vP;%dPol12|zC{rRmZ9(DBjwhK3L&NgdT=h$rxD3AbjZSas6^CdJ+>@I<-|sn ziOhA!z4094jonU?bmnGb)&l2~u4sO=WRvz{K2ah2M-EC?bpy#*=mN!~=+I{prOk!+ z>iJqiVvE!@ZLOj+(gA%kN+?PI=K5MiGj(Xc5TBLoYX}?_p(L1i0Wk!qUXt5iGr8%K zSV$pkeNIx&LfAgXA4sVMnRb8gZX*+8-L|u240 at C+V@`pxmKel at 6|2 at j>?d9fwe#yW z&^UlalO*6e`#*lt(5LKra~aCGi5t at eIj~DCf=Wk(Sc=iW_(tdbhxjFUvI^w+n|UNZ zwe-`-lK~)a!^?r`G`Jv3BMml*EhNCsPOYP^v=D55%^gy+JU9_QtWk&9m zxL64AB2*VOjAw3n9?Lq{DIfEsUwOOe^r&A7RK#wJ-KsbChS2zO&_A(|LTL1)`7Nn= z1FgTWV-NuGdVTH3tStk2yfP1(mccn8D%Yl~%3f*4&l+pN8456)?*UoZzOTXz$WREu z&bU}rr{|b5p3j$L96!$UQ*Oj5(VnxkuH?^(GWo_bYJ at U zF{=(m>T@`w8$6Z)yxI$}d=E*eBZZCJlO-LDMhJpx zJ1`oJgoF%SnNUkf&zkWW(QhMXeke#)iv5Ckz0{a$u(3MRM^s8gNfwowJ+U$7#;}?I zZ#Rp}Cyw at Du_;m`CCZ5%1K~iEqo|4335cKb5|jpuL%m&XAUI^?MF!v-|L1ox9!bo{cyWK2A}OSHf{Qy8gD}uzMx@mL*WG6yn>W4Xz0_Y zF2^a6k+4dqY3mwpJ85kZyy0K zKA=@Vu|P^?xT4T8ph52~E43nwatnAA)-^KVS39^yfE1^VmuD)hsG&UwR0v|bVvwp5 z&&af4Qu}07O at kRFGe!diag;Y{+pJU%<6*jsU`m837Bv}BWU#YSHFsXJFQ(b?t4n2p z7PMdCZ!++>!u;nP9g{apOZoKm#0F{r=C`i9N*v)TaQsWfF*0FS8&>k^1XJkMfHY5v z*NUxSE~Bp#4hCV^*$RyDWf0WA)SoSt+1Jv0t_-g+EW~|`Gi|fq86){2*;NCtctH9z zGtkq%MC*Abtt>a&XBdItuXSMg`7~v-T$0t>@2WxBtJ9B5nA*u4JIZk%{Pp zL%dC_s}|+j?P*tA>m?eR7r6U7+D}`wzLSVFfL(iK(n2}^R7-l!i)b442JA*5|W1eNW zh8iMs5xQTniY9hE$|^*9TCk#BvW29O;6w{D37+Acv5A5ymL4+ZxRb9gC-CS0-1+|( z at YmfEALxLp@5&7|2TqwbQ((*_89Ob1ZOyE(g--icZa-sP65~#GN-YikG8*j+C{286 zH_r!-kTc`?y6 at n=J>b;_U2HIH7=49yymKQu-N~+F`-uM)TzRK_fJiHWdoA9>n4Rv= zbf9VtN?9&OiTS{W;9qq}H#{7f<@W92nQUMmRMOKirl0SL9uTM8qI#_a{ki$M~eJ?JaVi zZ<{+OzM40DvvjE(SZ-jh`ppGyATD z?tFOi~Pb6nJQ~-2;Enj8I&GSWvPpcJ&gf|50%a_ulj+!>^C>VJG zj`CG0_aYteh4ZHPJf__D5PtOmhg}(p_2I z+esD`=P3*_6-f7d0iolta|4Q}BA;0~pjgiG6X4;FLz!;yg;2q)BupUxj93^^8`1Z= zRb{P at zTh_6-s*Lsjv7RVdcPDW3~&9D_r9yWfx1NHBN1}&_U@)SlTJ#1vah0lYobw} zlDXyB-E>o#M=!S^t2IFeAItUgeu(^!3B|1S!nmoqAL;7F&-gw$>{u*OX{+Y%35>7Z zux-Nfc7$W{S5Fiyx~!8Beczg|-mC5AUc2bxO={Y2#?%kT=xekinM%no9pUztWiy`n z+!`+Vm?u1${shnz?ejibNTR`SJSl9Isy!C4oa>B6LZ at UkCu9WWG4_^?yD|ks{^a*> zfYaLGl#Or<)7IS48XRGB!FzmGCB~+Te;ug!E*6mShpQZ^c-$MF8 at MP!Ih)(6y>EmM za8FOrRs5SRGvIctJ}m~f)1cx#AAnz7n8WhqFG7FTRRf93zU`Vex|A at rTxnx3@oJ(c za>QDiIeGLZOex#aa_#9M(cc%NOZke_(r&lWaVKF{SpzJO9nv5-opl7~qs|J4efRK) z{`p;eTnn*U-On1aI_2nBx1H^%5nCHO%EDZTe-ssJvIZPlqPN~(re++t<4c=GMn!IZ zxOgypC;Oza-hop;4qf&UGXCy$+9TbLvX4dkyGB at FE$48(W^}hjiqW^#W%q> zV+t at ju^j;|?q^Ca4QSUJ+riJ5*v8`>QX^NQF-m`-f3Ij4ru=&C-?IY=G^&PkkNr{P zzgBBy$y?wVs3V|3e*oUX z;7vgLY#)BD9Y~<2>*Bq3p!7Hp1|MD99%4hGhlP6TdC6KXjM@(VLg|W)=n;naUq>iA ztjd^N;R{!RXYsrq#|Ufb*<##;FxRu<#QpAog>@p?U8IwVWEW%-%H+vg^B7c{r9X?8 zC1r+kL%|XDFF?e3tq1eT(1>$YaxpSuF)GX5x+<%&{D-mZZR~a0Xr z at r;0a7*({LI3TG}6F3BSe!rj{LHMt|?blAq!z>MhC?6o?fQDs3U!p%gq*X4XuVRh| z*MSoYVl`rc2TY5 za2KPf%vTv}#H+D|Ujj`;m-`Y;(}O0SgHahPp-x9c&sr*AVKupOIwm3-vP7j%07qppt->>Gl5M&aEc z*<(53XaG#LQ90p`P_bmLwxm}fpC26?mmAW*NPY(lLZyF)r83o*zlXLH91SmGAF^EE z#D2@?7mIyCR7S*p@(zbD#C~OP^u+#g(poc-e;C>4uSYDbS at Pdp4bqE!D4H`Y_SI!G zD)xT`LN_Azv#%40B9Qwa at BX~h{Vw#&<$r%=2>GA&2J?|bNOh=2_aoK_!?@5Vd9R(0 z3Vjz(`7ZQH-fK^9LLUr~Uyxbc5D_gJVE@#YlJ)dDd{g2t-gWxLEjp2tYe3w4ZH)e8 z!Zaf5Fld?J${fQ2$p9Naps^$TR8qmlf3NVjNWl#sTFdn^Spl+FW{YaER6|MmS`IAv zz=7jVK<;u3O~vi1LZGYT$381liiLMWB0p5DWBA9$6=bbndt<7C_C$omS=O-McKRXoIncS)m0Cn;mmeK~v?p zpJ5q`CsFw!u-9Q&ap0&oteZa{N?=yK5yV@#a2>kd)b;9o=-;pECAc%)$D}q0Il3cf zMr$$YR4IItH6bb%$XSZL&J{R$E6;4?1RhFWc^Qj}i6SQ7t- at juvasu4YPOnG-o=`Q zoc6m~LByuy9=r(Oq4mmGR at E;$plz|YY90l86`#hsx^%GtX2bL1Q< z7cI0=l2r#yL;z$RweW|+KwlC-!0Hh|LAaJEsod|laxo|cJITlEq(li!*tul!>*h%_Hs zE7o;ZNu^tc$Kx_NpK)ovEL-S&-g;L9!-cRnh>Pehyit}0>cg(3)>r^t_Dj%!`Xn}V z0~d|dRwYJT3_?Lkmw^NMrie5qJ0cP#oF&TUvb^O1Rpuw-@!I9y_A8IzDj$DnE1#6l ze;?50&b9l!%Orwwm;&0jcEJ2Vt1F@#!yuthvC7h9hY>_TChOJd?|LAx1Tga4nHj*b zv2Uf~q2Lx6tZ_iH_Xn=$qD)v~>1q_7^1M3KSPRaT2kik?W-Tckb4lSyly;$p0$8F= ziPjWml}`QT9bg7KRi(%B at gf%B=)zSPBU}>9Q7sQ*knjwdh-Z_a(Yaj&L_}qDV at aDy z@#HlZ0iz}xx3Gf&s+5CP7n+AG{DWHX>tcoUx3%Dr56CGBLed?Ns1h3 at miuR~i`?a{ zj;$8mw&JZ$cG^VYdm7+<5!H?GEI>7XUtN~Q*3tR+(akhE@^uT6EQ-Pfb^e${e!#z~ zu+_J#Mxr^$Q4CMStO*e*j>zuByUEhtFBzNAss_x}tmvTT*%pa9EJ#vaUY#VrBUYCK z%Tgak+*PlHZX)%ne=kI>O$^f7pZ at 0d08*#-zaDdQtP6zlBXGln;{G6~^qN46`2KJS z=P~B)(g=TB+0+_=>F%_GuLtk||V<42_}Cht=|$1P}9bl#Qu6>ujS at 2JY=t!U;x=g;~nTZIxgH z0wniSd>llVJJj=M9g^=f)%s8(9Hz*67Qpo&Yy%iAg6#1;8&d>33g<~BPN4T;Gmm(k z+%v8N)26mN%fJ50een?Re(%z$7YPqNbb{we)d7w~M~gQ6%k#xY2E&tkWBa^GZn zm96nqP6TdbT93*VE~=>f;9f76#fC1!_J5KjP=*@;^~`o7}{ zM*EJ&RRf#rW*d_~W*Pg99k z3>%j1X@@<_C*Wdfeme<$smZnDbD$N~>?FUzFbP|ik;FJi_4|@hiHsszVKsoDQmL8< zMC0n?n>ibxN+MU7a5a+UebzkOj>1EC1r^Yh$1L}hf{S2zVt-WOxujnOmRt4GXFeRW zVY*Kd#-}LDQn23VFW#YL_ezIS$42X}P8k3Lu~HTf)p6GAaJ;lA7mZSeQQ}&j35lgYnLUCzqk5Gak?H zPlDr0o}x3?Be-(uqtmZDDU~e*5go z04BZ)f$jkW89|R53j$0XuEy at An3_P%wUnX25-9hj({=MVeyJB4U+Ls#N-$T+hHDLW zQ(X++;I-FbxkEYE3&Vv1H8MmV20*G~LlDljD9H>yJ|Avuhsc#PU3?`rh-UJD5eE at - z2-+xb;XH#`I1f}_motqlFe!2v+ZigYbr7ci4?RCA3ZK2vnWHz&d6(0RX%< zQs>H2k|2hm ziQCpN%`P;FTg;)%x|-cSwQFPxas7gO7_Gqzj9c9%_YP|#Nm4lo<-{BfasJLlw;~ao z1yoMd$okeH#_z5l5j?m&SXC~uJuoz(42~SJL&Mk at G8(>z;uw(nus`5^?A7r>nk+*W zqXF9V_h)ECCbQg;6ka98F%(9 at U~E<*7WJlOx#vkNU)E#z)+JTcKnL3SQk{gYO#SN# zwV2txl-~zx-Sz|#22ZK6O{O at Y!iSlM0en-T1bdq_+^v;?-Dk&FntM4IdN&j%AC$Z9 zlVl&T0+ at T1kpIKnHjS%-H&1D>4L!sPnunf~BxN%0e8X_BOBXot#aY_3E|R~Titkcl zN}9osmjRQNRdv1y+bF{3swyC`_UH>6Rh^ObzyaPae` zU(gFn5W75ilpr2U60 at ob%UrISN_y_4AzqAiW3WUxq6`cfTR_3Ny zBwi9a-DU8^1JoeG)18B#%0D_|Pb1n5JZRJt1-_#xuo&|ogzwN-5oo+tJlYUtxJK4BpdpzITnxijT z{-ZgwQVo$xH*DDso;|f24AQ4yui2&AINI1{7Cedvh3Vi0RdAcDt%ArDhZeno-KIKv zD_D_+&;iB|_{u{{ia25L6`V(SM!M^4F43w+pXmxyJs!CkHvs%(( zQv(h$c2M`PRB|?HSp8jHBPNJO#1Uq&YobRvYuDt}%#9|`YNjahWX(A%F0lavN$IC< zTdwg_)KmVeD(km{P0y9>JozMGHL!76#{)XT{OFQ?knM2Y+oi zZ`JVm);_|JK at XKpWwD6G!dX?Ry*Sl;R(XX2hKIg^2 zfkwyx&ad0lKY>2YnXTnk`uHrqGfn%3{v-9#YqCZm&TYxkG=bG^7+cR)55|sS(i8xC z4G#0c$Yq>AOoM}K-(1k+A7k!zf_rSep%;@AM5FjQ224)5sd0z3U79|wp6)ERc~@_A zhMd4LdEJ8?8l6EEjb!ZA0T)+XA at kkE1vUD0QzHY*Y&>!>rhV%4uONTGZPEMg6#GP~ zJ!FTE-sN@|b0wQ3iz=k^RBn_lCeT7A(_J1)tQ*t!JKHYZu{GIfV4#@nEnzk0Sf5y1 z1fI1?1PTU=4{CUyle9O at M8Wvy<)1;_HeEY<+KFJQg3Z7AIX9n{7ZFFFG$Z at K9yj5jj1 zX5jy~S$kH%J8 at YD3iC>@3nf}P_9hP!Xl1-n7U6a2{8ubxZCb}H8z0RGj109XU<$g>A>}v0 z z{gc{AjVq;(2^}6|<6hqjVRaKWqbJDBa8||Dt zbg1m84IOB%S=kavIHO!MbhtR;F?zG}1c?>uCQ%zra>kims49ji| zI0t=2mXSU at +VCSEOtVWv;|zh|zk&tvTfE6+vMex30^j~w?Gs~l zM2xO-v85@_)SmPy>8-K2H7sbf>n}nlnkM=vEGVMD2|d(> zZs1`+7eib_Wu47_eBcv}eaQG=!3-JvD+B8fqZ)w+eZ}}v(xUg_nuizSETVI}nCw{) zKE~{pB55$IQQ#{Tc00+Bb*85g#4EFfr;qBDvj+K^0YOlMjfwxvLBd at PV&})7R?`a! zM`73YuDV@<5VSDKtcx%2oOz`CB$xYW=mboH#rlS?T~|&4;6VD%2R3S2=xUqmo-{Vv z??kdm at d7N;MD0e0%cKk8Rnwq zNyG-f2{Iu7yiOeSVPh^ZMznO0wrL>f!U1P0RA#4Sv~k4;AyO44Vxy~KQk!TMKA0dt z7A5wefvK at RVNie#l`jc_Yv60vyZ|K{1ie(Ldzcidd})L3R|eq%CA_JD)Y`l#B#15! zXAN2pQmVZ6x>XTOu->x%FWcnNImX3>b`lJJu1DdPB#&soe0e1ynLDeAq=fPP19GPh zAk0QV7y9cU at C=#YzyxeH3)qck2AYC^CVz}#8-&A=6Pre4& zyX#v}s9GZ}j*}5hsULY1RTvXZL)YZhh%5G}h3>jAtf_VQHO_}@KH9-D+>NaiD at FFp-Qz#tiJ>&w_D)h{Vm{-D<2#(KQVW64jNcz0c_vlv@*{GmN1$ zER8Z$POzI-onRg}vy|*BD%SIr<7rk%1jxThT5UEmkEzrFTA%MXxk`}VjjW&@h0A`M4#5)fy#qzxX!Y33%dMbE&lva{(d$MJ6W+4GXhxO3qRLz4H}YwAO+i+ zi}=Q&-MUgb19|+!`6GgPK at ot=@rXZBzY^oLX8)0JilPza7Lt^o|G4lE*7?jP8t_Mw zN+LR$nc4`%KtgFfZ!w?u=b1_qpXb>&e4Y_MC>1Tlc!EVM-&zD&e6C$XNaI|JCAApk zThw~n$QoJVZAdEc#Bl+D%06+l_qI=s}I0dRJR0pL5-s30#|pC=!-_8;#VH&jl<{9Y3pRwof!4_ zP(8?ocg#gq6XDe);w*Z%Z|zw at 0+8%wQbSe-bL)UQ7QJi=t7{5-02akM-l9k9#tG0- z<2xN}fEw;+nQbQxBhtRidV*gMeN&i>ASMM{A1tr-yewjcpeDOcRg!z-bnBTyQ)!+g zo at ARqeS$O)ywsHGnnp_sw29i<&Iv=XOvW(}5!{4o$(8r+vl-oUk>2@;4?cEhdept6 zbfP!W4 at P7dG$n|TM6apNQ?$g at ook(%Nh(njvxo;+KI@=V6o*meYTqqXvY>HIjf)G@ z2A;oB7M4c-hO&6U097BREE9z_SNERuh)fBZ9@@_8uA~XHmj=-V7c9b(8TzxWQstyI zNh?TuH8uez at JKvk?%iZUA4kQ9dC4126ytYz=S`L^$sB#sQ42@;>S_>Cl4uBOu)o%m z at bw==mIN!P&t5V;p{SIQOkhxBwKeR at npmhCL&od#D~zN%#C7dMLvX4fb!SNL5ckBk&6NOA+Fc~Zow1=@Vd545i3(1z38^J#_CDaY_@YTIZxr^q+)TW50$bdPdMk_<;z+7xO0uvuu8Qwf=wSB#@NN-T*kMRb+o>Vl~ zwIc%@M3#1CvN#J`SXJP$eY2+B&UuqMvU?+wy^{{b%K2WsB|+5;lhM at x7fdVw>(;Zp zz!O_cL9t%_!v9!Cs6!zZbEq(*cBVd|m at q(cmH-rP4FoTj zI;BEejpwo^&t{)KQXsdvz~9`bO at t|gketgnOD?z`_{afjM}FqHL*=4B`39G#wqCwS z<@xVH50-0I=mM3`@3|)5gDl{cy5FesVwP5_yqi}xu+`*(^sKdhbn}mDY>440!h8`- zm=9vDx+lq8WYlPus^}qMOg_vyYQ9gAT~ZcJ;XYpw9j^unU#gam#7H$*OVu3g03s^J zc%G)`ds87>#3|J&EVv at E{i^a=9f{t(XDqa2>IJt7 zCe%#zEW at _g==;0cPlN|V{8Uec8=k89G4OD|+G>B|LXx%p%HIB7wVzrRLdzOZu_(bC zmLjnpWnQWUgg}iy0#NBjRGj&2S#m}0WgjsA!{FvK=?tpRf9)B|(mk6@^dmJiI=os!(&Che3 zHk0(mig^4=AsO5zDIsyawe+dyjjmho6Q2{lbO8#E-)G{F`9u#7dhs&z!SR at H3!$+H zqdl}Q at 9dFb2YeMwVfg2a6ghW~uAj|IQ at Mm8Tr*iKS7%%3ia96ggM1)J$=V!?Zf{Dk zAI2{^*rCa_`fh_TIg7GD8qsjNw0_O|3EiyOWzS!Kh^jh=PkGzS|v zzW#%|3&-wQQ8`!!i51{(vpRSQVL^Fug7|p$HHFr`e z2kU~6#yy18M;HSjJWZg%VGPHMH|O)XIyB18Q$uRANw{bE?~(ueC|^_gb=Loqd*Jh1 zKIFGHdu)NHrw5VCpC)Q)_QXYAIh!wk z@`N http://hg.python.org/cpython/rev/60acd04d5613 changeset: 76336:60acd04d5613 user: Brett Cannon date: Sun Apr 15 19:06:23 2012 -0400 summary: Consider load_dynamic() something to keep in _imp. files: Lib/imp.py | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -7,13 +7,14 @@ """ # (Probably) need to stay in _imp from _imp import (lock_held, acquire_lock, release_lock, reload, - get_frozen_object, is_frozen_package, init_builtin, - init_frozen, is_builtin, is_frozen, _fix_co_filename) + load_dynamic, get_frozen_object, is_frozen_package, + init_builtin, init_frozen, is_builtin, is_frozen, + _fix_co_filename) # Can (probably) move to importlib from _imp import (get_magic, get_tag, get_suffixes, cache_from_source, source_from_cache) # Should be re-implemented here (and mostly deprecated) -from _imp import (find_module, load_module, load_compiled, load_dynamic, +from _imp import (find_module, load_module, load_compiled, load_package, load_source, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 01:06:48 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 16 Apr 2012 01:06:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/2e6acfa3509e changeset: 76337:2e6acfa3509e parent: 76336:60acd04d5613 parent: 76334:c3a0197256ee user: Brett Cannon date: Sun Apr 15 19:06:40 2012 -0400 summary: merge files: Doc/c-api/dict.rst | 8 +- Doc/library/stdtypes.rst | 16 +- Doc/library/types.rst | 52 +++++++ Doc/whatsnew/3.3.rst | 7 + Lib/test/test_descr.py | 4 +- Lib/test/test_types.py | 184 ++++++++++++++++++++++++++- Lib/types.py | 1 + Misc/NEWS | 2 + Objects/descrobject.c | 170 ++++++++++++++++-------- 9 files changed, 369 insertions(+), 75 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -36,11 +36,11 @@ Return a new empty dictionary, or *NULL* on failure. -.. c:function:: PyObject* PyDictProxy_New(PyObject *dict) +.. c:function:: PyObject* PyDictProxy_New(PyObject *mapping) - Return a proxy object for a mapping which enforces read-only behavior. - This is normally used to create a proxy to prevent modification of the - dictionary for non-dynamic class types. + Return a :class:`types.MappingProxyType` object for a mapping which + enforces read-only behavior. This is normally used to create a view to + prevent modification of the dictionary for non-dynamic class types. .. c:function:: void PyDict_Clear(PyObject *p) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2258,13 +2258,13 @@ .. method:: items() - Return a new view of the dictionary's items (``(key, value)`` pairs). See - below for documentation of view objects. + Return a new view of the dictionary's items (``(key, value)`` pairs). + See the :ref:`documentation of view objects `. .. method:: keys() - Return a new view of the dictionary's keys. See below for documentation of - view objects. + Return a new view of the dictionary's keys. See the :ref:`documentation + of view objects `. .. method:: pop(key[, default]) @@ -2298,8 +2298,12 @@ .. method:: values() - Return a new view of the dictionary's values. See below for documentation of - view objects. + Return a new view of the dictionary's values. See the + :ref:`documentation of view objects `. + +.. seealso:: + :class:`types.MappingProxyType` can be used to create a read-only view + of a :class:`dict`. .. _dict-views: diff --git a/Doc/library/types.rst b/Doc/library/types.rst --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -85,3 +85,55 @@ In other implementations of Python, this type may be identical to ``GetSetDescriptorType``. + +.. class:: MappingProxyType(mapping) + + Read-only proxy of a mapping. It provides a dynamic view on the mapping's + entries, which means that when the mapping changes, the view reflects these + changes. + + .. versionadded:: 3.3 + + .. describe:: key in proxy + + Return ``True`` if the underlying mapping has a key *key*, else + ``False``. + + .. describe:: proxy[key] + + Return the item of the underlying mapping with key *key*. Raises a + :exc:`KeyError` if *key* is not in the underlying mapping. + + .. describe:: iter(proxy) + + Return an iterator over the keys of the underlying mapping. This is a + shortcut for ``iter(proxy.keys())``. + + .. describe:: len(proxy) + + Return the number of items in the underlying mapping. + + .. method:: copy() + + Return a shallow copy of the underlying mapping. + + .. method:: get(key[, default]) + + Return the value for *key* if *key* is in the underlying mapping, else + *default*. If *default* is not given, it defaults to ``None``, so that + this method never raises a :exc:`KeyError`. + + .. method:: items() + + Return a new view of the underlying mapping's items (``(key, value)`` + pairs). + + .. method:: keys() + + Return a new view of the underlying mapping's keys. + + .. method:: values() + + Return a new view of the underlying mapping's values. + + diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1068,6 +1068,13 @@ (Contributed by Victor Stinner in :issue:`10278`) +types +----- + +Add a new :class:`types.MappingProxyType` class: Read-only proxy of a mapping. +(:issue:`14386`) + + urllib ------ diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4574,11 +4574,11 @@ self.assertEqual(type(C.__dict__), type(B.__dict__)) def test_repr(self): - # Testing dict_proxy.__repr__. + # Testing mappingproxy.__repr__. # We can't blindly compare with the repr of another dict as ordering # of keys and values is arbitrary and may differ. r = repr(self.C.__dict__) - self.assertTrue(r.startswith('dict_proxy('), r) + self.assertTrue(r.startswith('mappingproxy('), r) self.assertTrue(r.endswith(')'), r) for k, v in self.C.__dict__.items(): self.assertIn('{!r}: {!r}'.format(k, v), r) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1,9 +1,11 @@ # Python test set -- part 6, built-in types from test.support import run_unittest, run_with_locale +import collections +import locale +import sys +import types import unittest -import sys -import locale class TypesTests(unittest.TestCase): @@ -569,8 +571,184 @@ self.assertGreater(tuple.__itemsize__, 0) +class MappingProxyTests(unittest.TestCase): + mappingproxy = types.MappingProxyType + + def test_constructor(self): + class userdict(dict): + pass + + mapping = {'x': 1, 'y': 2} + self.assertEqual(self.mappingproxy(mapping), mapping) + mapping = userdict(x=1, y=2) + self.assertEqual(self.mappingproxy(mapping), mapping) + mapping = collections.ChainMap({'x': 1}, {'y': 2}) + self.assertEqual(self.mappingproxy(mapping), mapping) + + self.assertRaises(TypeError, self.mappingproxy, 10) + self.assertRaises(TypeError, self.mappingproxy, ("a", "tuple")) + self.assertRaises(TypeError, self.mappingproxy, ["a", "list"]) + + def test_methods(self): + attrs = set(dir(self.mappingproxy({}))) - set(dir(object())) + self.assertEqual(attrs, { + '__contains__', + '__getitem__', + '__iter__', + '__len__', + 'copy', + 'get', + 'items', + 'keys', + 'values', + }) + + def test_get(self): + view = self.mappingproxy({'a': 'A', 'b': 'B'}) + self.assertEqual(view['a'], 'A') + self.assertEqual(view['b'], 'B') + self.assertRaises(KeyError, view.__getitem__, 'xxx') + self.assertEqual(view.get('a'), 'A') + self.assertIsNone(view.get('xxx')) + self.assertEqual(view.get('xxx', 42), 42) + + def test_missing(self): + class dictmissing(dict): + def __missing__(self, key): + return "missing=%s" % key + + view = self.mappingproxy(dictmissing(x=1)) + self.assertEqual(view['x'], 1) + self.assertEqual(view['y'], 'missing=y') + self.assertEqual(view.get('x'), 1) + self.assertEqual(view.get('y'), None) + self.assertEqual(view.get('y', 42), 42) + self.assertTrue('x' in view) + self.assertFalse('y' in view) + + def test_customdict(self): + class customdict(dict): + def __contains__(self, key): + if key == 'magic': + return True + else: + return dict.__contains__(self, key) + + def __iter__(self): + return iter(('iter',)) + + def __len__(self): + return 500 + + def copy(self): + return 'copy' + + def keys(self): + return 'keys' + + def items(self): + return 'items' + + def values(self): + return 'values' + + def __getitem__(self, key): + return "getitem=%s" % dict.__getitem__(self, key) + + def get(self, key, default=None): + return "get=%s" % dict.get(self, key, 'default=%r' % default) + + custom = customdict({'key': 'value'}) + view = self.mappingproxy(custom) + self.assertTrue('key' in view) + self.assertTrue('magic' in view) + self.assertFalse('xxx' in view) + self.assertEqual(view['key'], 'getitem=value') + self.assertRaises(KeyError, view.__getitem__, 'xxx') + self.assertEqual(tuple(view), ('iter',)) + self.assertEqual(len(view), 500) + self.assertEqual(view.copy(), 'copy') + self.assertEqual(view.get('key'), 'get=value') + self.assertEqual(view.get('xxx'), 'get=default=None') + self.assertEqual(view.items(), 'items') + self.assertEqual(view.keys(), 'keys') + self.assertEqual(view.values(), 'values') + + def test_chainmap(self): + d1 = {'x': 1} + d2 = {'y': 2} + mapping = collections.ChainMap(d1, d2) + view = self.mappingproxy(mapping) + self.assertTrue('x' in view) + self.assertTrue('y' in view) + self.assertFalse('z' in view) + self.assertEqual(view['x'], 1) + self.assertEqual(view['y'], 2) + self.assertRaises(KeyError, view.__getitem__, 'z') + self.assertEqual(tuple(sorted(view)), ('x', 'y')) + self.assertEqual(len(view), 2) + copy = view.copy() + self.assertIsNot(copy, mapping) + self.assertIsInstance(copy, collections.ChainMap) + self.assertEqual(copy, mapping) + self.assertEqual(view.get('x'), 1) + self.assertEqual(view.get('y'), 2) + self.assertIsNone(view.get('z')) + self.assertEqual(tuple(sorted(view.items())), (('x', 1), ('y', 2))) + self.assertEqual(tuple(sorted(view.keys())), ('x', 'y')) + self.assertEqual(tuple(sorted(view.values())), (1, 2)) + + def test_contains(self): + view = self.mappingproxy(dict.fromkeys('abc')) + self.assertTrue('a' in view) + self.assertTrue('b' in view) + self.assertTrue('c' in view) + self.assertFalse('xxx' in view) + + def test_views(self): + mapping = {} + view = self.mappingproxy(mapping) + keys = view.keys() + values = view.values() + items = view.items() + self.assertEqual(list(keys), []) + self.assertEqual(list(values), []) + self.assertEqual(list(items), []) + mapping['key'] = 'value' + self.assertEqual(list(keys), ['key']) + self.assertEqual(list(values), ['value']) + self.assertEqual(list(items), [('key', 'value')]) + + def test_len(self): + for expected in range(6): + data = dict.fromkeys('abcde'[:expected]) + self.assertEqual(len(data), expected) + view = self.mappingproxy(data) + self.assertEqual(len(view), expected) + + def test_iterators(self): + keys = ('x', 'y') + values = (1, 2) + items = tuple(zip(keys, values)) + view = self.mappingproxy(dict(items)) + self.assertEqual(set(view), set(keys)) + self.assertEqual(set(view.keys()), set(keys)) + self.assertEqual(set(view.values()), set(values)) + self.assertEqual(set(view.items()), set(items)) + + def test_copy(self): + original = {'key1': 27, 'key2': 51, 'key3': 93} + view = self.mappingproxy(original) + copy = view.copy() + self.assertEqual(type(copy), dict) + self.assertEqual(copy, original) + original['key1'] = 70 + self.assertEqual(view['key1'], 70) + self.assertEqual(copy['key1'], 27) + + def test_main(): - run_unittest(TypesTests) + run_unittest(TypesTests, MappingProxyTests) if __name__ == '__main__': test_main() diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -12,6 +12,7 @@ FunctionType = type(_f) LambdaType = type(lambda: None) # Same as FunctionType CodeType = type(_f.__code__) +MappingProxyType = type(type.__dict__) def _g(): yield 1 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,8 @@ Library ------- +- Issue #14386: Expose the dict_proxy internal type as types.MappingProxyType. + - Issue #13959: Make imp.reload() always use a module's __loader__ to perform the reload. diff --git a/Objects/descrobject.c b/Objects/descrobject.c --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -698,41 +698,44 @@ } -/* --- Readonly proxy for dictionaries (actually any mapping) --- */ +/* --- mappingproxy: read-only proxy for mappings --- */ /* This has no reason to be in this file except that adding new files is a bit of a pain */ typedef struct { PyObject_HEAD - PyObject *dict; -} proxyobject; + PyObject *mapping; +} mappingproxyobject; static Py_ssize_t -proxy_len(proxyobject *pp) +mappingproxy_len(mappingproxyobject *pp) { - return PyObject_Size(pp->dict); + return PyObject_Size(pp->mapping); } static PyObject * -proxy_getitem(proxyobject *pp, PyObject *key) +mappingproxy_getitem(mappingproxyobject *pp, PyObject *key) { - return PyObject_GetItem(pp->dict, key); + return PyObject_GetItem(pp->mapping, key); } -static PyMappingMethods proxy_as_mapping = { - (lenfunc)proxy_len, /* mp_length */ - (binaryfunc)proxy_getitem, /* mp_subscript */ +static PyMappingMethods mappingproxy_as_mapping = { + (lenfunc)mappingproxy_len, /* mp_length */ + (binaryfunc)mappingproxy_getitem, /* mp_subscript */ 0, /* mp_ass_subscript */ }; static int -proxy_contains(proxyobject *pp, PyObject *key) +mappingproxy_contains(mappingproxyobject *pp, PyObject *key) { - return PyDict_Contains(pp->dict, key); + if (PyDict_CheckExact(pp->mapping)) + return PyDict_Contains(pp->mapping, key); + else + return PySequence_Contains(pp->mapping, key); } -static PySequenceMethods proxy_as_sequence = { +static PySequenceMethods mappingproxy_as_sequence = { 0, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ @@ -740,152 +743,199 @@ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)proxy_contains, /* sq_contains */ + (objobjproc)mappingproxy_contains, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ }; static PyObject * -proxy_get(proxyobject *pp, PyObject *args) +mappingproxy_get(mappingproxyobject *pp, PyObject *args) { PyObject *key, *def = Py_None; _Py_IDENTIFIER(get); if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) return NULL; - return _PyObject_CallMethodId(pp->dict, &PyId_get, "(OO)", key, def); + return _PyObject_CallMethodId(pp->mapping, &PyId_get, "(OO)", key, def); } static PyObject * -proxy_keys(proxyobject *pp) +mappingproxy_keys(mappingproxyobject *pp) { _Py_IDENTIFIER(keys); - return _PyObject_CallMethodId(pp->dict, &PyId_keys, NULL); + return _PyObject_CallMethodId(pp->mapping, &PyId_keys, NULL); } static PyObject * -proxy_values(proxyobject *pp) +mappingproxy_values(mappingproxyobject *pp) { _Py_IDENTIFIER(values); - return _PyObject_CallMethodId(pp->dict, &PyId_values, NULL); + return _PyObject_CallMethodId(pp->mapping, &PyId_values, NULL); } static PyObject * -proxy_items(proxyobject *pp) +mappingproxy_items(mappingproxyobject *pp) { _Py_IDENTIFIER(items); - return _PyObject_CallMethodId(pp->dict, &PyId_items, NULL); + return _PyObject_CallMethodId(pp->mapping, &PyId_items, NULL); } static PyObject * -proxy_copy(proxyobject *pp) +mappingproxy_copy(mappingproxyobject *pp) { _Py_IDENTIFIER(copy); - return _PyObject_CallMethodId(pp->dict, &PyId_copy, NULL); + return _PyObject_CallMethodId(pp->mapping, &PyId_copy, NULL); } -static PyMethodDef proxy_methods[] = { - {"get", (PyCFunction)proxy_get, METH_VARARGS, +/* WARNING: mappingproxy methods must not give access + to the underlying mapping */ + +static PyMethodDef mappingproxy_methods[] = { + {"get", (PyCFunction)mappingproxy_get, METH_VARARGS, PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d." - " d defaults to None.")}, - {"keys", (PyCFunction)proxy_keys, METH_NOARGS, + " d defaults to None.")}, + {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS, PyDoc_STR("D.keys() -> list of D's keys")}, - {"values", (PyCFunction)proxy_values, METH_NOARGS, + {"values", (PyCFunction)mappingproxy_values, METH_NOARGS, PyDoc_STR("D.values() -> list of D's values")}, - {"items", (PyCFunction)proxy_items, METH_NOARGS, + {"items", (PyCFunction)mappingproxy_items, METH_NOARGS, PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")}, - {"copy", (PyCFunction)proxy_copy, METH_NOARGS, + {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS, PyDoc_STR("D.copy() -> a shallow copy of D")}, {0} }; static void -proxy_dealloc(proxyobject *pp) +mappingproxy_dealloc(mappingproxyobject *pp) { _PyObject_GC_UNTRACK(pp); - Py_DECREF(pp->dict); + Py_DECREF(pp->mapping); PyObject_GC_Del(pp); } static PyObject * -proxy_getiter(proxyobject *pp) +mappingproxy_getiter(mappingproxyobject *pp) { - return PyObject_GetIter(pp->dict); + return PyObject_GetIter(pp->mapping); } static PyObject * -proxy_str(proxyobject *pp) +mappingproxy_str(mappingproxyobject *pp) { - return PyObject_Str(pp->dict); + return PyObject_Str(pp->mapping); } static PyObject * -proxy_repr(proxyobject *pp) +mappingproxy_repr(mappingproxyobject *pp) { - return PyUnicode_FromFormat("dict_proxy(%R)", pp->dict); + return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping); } static int -proxy_traverse(PyObject *self, visitproc visit, void *arg) +mappingproxy_traverse(PyObject *self, visitproc visit, void *arg) { - proxyobject *pp = (proxyobject *)self; - Py_VISIT(pp->dict); + mappingproxyobject *pp = (mappingproxyobject *)self; + Py_VISIT(pp->mapping); return 0; } static PyObject * -proxy_richcompare(proxyobject *v, PyObject *w, int op) +mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op) { - return PyObject_RichCompare(v->dict, w, op); + return PyObject_RichCompare(v->mapping, w, op); +} + +static int +mappingproxy_check_mapping(PyObject *mapping) +{ + if (!PyMapping_Check(mapping) + || PyList_Check(mapping) + || PyTuple_Check(mapping)) { + PyErr_Format(PyExc_TypeError, + "mappingproxy() argument must be a mapping, not %s", + Py_TYPE(mapping)->tp_name); + return -1; + } + return 0; +} + +static PyObject* +mappingproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"mapping", NULL}; + PyObject *mapping; + mappingproxyobject *mappingproxy; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:mappingproxy", + kwlist, &mapping)) + return NULL; + + if (mappingproxy_check_mapping(mapping) == -1) + return NULL; + + mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type); + if (mappingproxy == NULL) + return NULL; + Py_INCREF(mapping); + mappingproxy->mapping = mapping; + _PyObject_GC_TRACK(mappingproxy); + return (PyObject *)mappingproxy; } PyTypeObject PyDictProxy_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict_proxy", /* tp_name */ - sizeof(proxyobject), /* tp_basicsize */ + "mappingproxy", /* tp_name */ + sizeof(mappingproxyobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)proxy_dealloc, /* tp_dealloc */ + (destructor)mappingproxy_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - (reprfunc)proxy_repr, /* tp_repr */ + (reprfunc)mappingproxy_repr, /* tp_repr */ 0, /* tp_as_number */ - &proxy_as_sequence, /* tp_as_sequence */ - &proxy_as_mapping, /* tp_as_mapping */ + &mappingproxy_as_sequence, /* tp_as_sequence */ + &mappingproxy_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ - (reprfunc)proxy_str, /* tp_str */ + (reprfunc)mappingproxy_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - proxy_traverse, /* tp_traverse */ + mappingproxy_traverse, /* tp_traverse */ 0, /* tp_clear */ - (richcmpfunc)proxy_richcompare, /* tp_richcompare */ + (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - (getiterfunc)proxy_getiter, /* tp_iter */ + (getiterfunc)mappingproxy_getiter, /* tp_iter */ 0, /* tp_iternext */ - proxy_methods, /* tp_methods */ + mappingproxy_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 */ + mappingproxy_new, /* tp_new */ }; PyObject * -PyDictProxy_New(PyObject *dict) +PyDictProxy_New(PyObject *mapping) { - proxyobject *pp; + mappingproxyobject *pp; - pp = PyObject_GC_New(proxyobject, &PyDictProxy_Type); + if (mappingproxy_check_mapping(mapping) == -1) + return NULL; + + pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type); if (pp != NULL) { - Py_INCREF(dict); - pp->dict = dict; + Py_INCREF(mapping); + pp->mapping = mapping; _PyObject_GC_TRACK(pp); } return (PyObject *)pp; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 02:25:28 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 16 Apr 2012 02:25:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Re-implem?= =?utf8?q?ent_imp=2Eload=5Fmodule=28=29_in_imp=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/2df37938b8e1 changeset: 76338:2df37938b8e1 user: Brett Cannon date: Sun Apr 15 20:25:23 2012 -0400 summary: Issue #13959: Re-implement imp.load_module() in imp.py. files: Lib/imp.py | 29 +++++++++++++++++++- Python/import.c | 53 ------------------------------------- 2 files changed, 28 insertions(+), 54 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -14,10 +14,37 @@ from _imp import (get_magic, get_tag, get_suffixes, cache_from_source, source_from_cache) # Should be re-implemented here (and mostly deprecated) -from _imp import (find_module, load_module, load_compiled, +from _imp import (find_module, load_compiled, load_package, load_source, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, PY_CODERESOURCE, IMP_HOOK) from importlib._bootstrap import _new_module as new_module + + +def load_module(name, file, filename, details): + """Load a module, given information returned by find_module(). + + The module name must include the full package name, if any. + + """ + suffix, mode, type_ = details + if mode and (not mode.startswith(('r', 'U'))) or '+' in mode: + raise ValueError('invalid file open mode {!r}'.format(mode)) + elif file is None and type_ in {PY_SOURCE, PY_COMPILED}: + msg = 'file object required for import (type code {})'.format(type_) + raise ValueError(msg) + elif type_ == PY_SOURCE: + return load_source(name, filename, file) + elif type_ == PY_COMPILED: + return load_compiled(name, filename, file) + elif type_ == PKG_DIRECTORY: + return load_package(name, filename) + elif type_ == C_BUILTIN: + return init_builtin(name) + elif type_ == PY_FROZEN: + return init_frozen(name) + else: + msg = "Don't know how to import {} (type code {}".format(name, type_) + raise ImportError(msg, name=name) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -3601,53 +3601,6 @@ } static PyObject * -imp_load_module(PyObject *self, PyObject *args) -{ - PyObject *name, *fob, *pathname, *pathname_obj, *ret; - char *suffix; /* Unused */ - char *mode; - int type; - FILE *fp; - - if (!PyArg_ParseTuple(args, "UOO(ssi):load_module", - &name, &fob, &pathname_obj, &suffix, &mode, &type)) - return NULL; - if (pathname_obj != Py_None) { - if (!PyUnicode_FSDecoder(pathname_obj, &pathname)) - return NULL; - } - else - pathname = NULL; - - if (*mode) { - /* Mode must start with 'r' or 'U' and must not contain '+'. - Implicit in this test is the assumption that the mode - may contain other modifiers like 'b' or 't'. */ - - if (!(*mode == 'r' || *mode == 'U') || strchr(mode, '+')) { - PyErr_Format(PyExc_ValueError, - "invalid file open mode %.200s", mode); - Py_XDECREF(pathname); - return NULL; - } - } - if (fob == Py_None) - fp = NULL; - else { - fp = get_file(NULL, fob, mode); - if (fp == NULL) { - Py_XDECREF(pathname); - return NULL; - } - } - ret = load_module(name, fp, pathname, type, NULL); - Py_XDECREF(pathname); - if (fp) - fclose(fp); - return ret; -} - -static PyObject * imp_load_package(PyObject *self, PyObject *args) { PyObject *name, *pathname; @@ -3757,11 +3710,6 @@ The module name cannot contain '.'; to search for a submodule of a\n\ package, pass the submodule name and the package's __path__."); -PyDoc_STRVAR(doc_load_module, -"load_module(name, file, filename, (suffix, mode, type)) -> module\n\ -Load a module, given information returned by find_module().\n\ -The module name must include the full package name, if any."); - PyDoc_STRVAR(doc_get_magic, "get_magic() -> string\n\ Return the magic number for .pyc or .pyo files."); @@ -3797,7 +3745,6 @@ {"get_magic", imp_get_magic, METH_NOARGS, doc_get_magic}, {"get_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, {"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes}, - {"load_module", imp_load_module, METH_VARARGS, doc_load_module}, {"lock_held", imp_lock_held, METH_NOARGS, doc_lock_held}, {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 03:38:36 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 03:38:36 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NTg5?= =?utf8?q?=3A_Update_certificate_chain_for_sha256=2Etbs-internet=2Ecom=2C_?= =?utf8?q?fixing_a?= Message-ID: http://hg.python.org/cpython/rev/f323b37ef6c1 changeset: 76339:f323b37ef6c1 branch: 3.2 parent: 76323:35a3a7e0d66d user: Antoine Pitrou date: Mon Apr 16 03:34:44 2012 +0200 summary: Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing a test failure in test_ssl. files: Lib/test/sha256.pem | 231 ++++++++++++++++--------------- Misc/NEWS | 6 + 2 files changed, 122 insertions(+), 115 deletions(-) diff --git a/Lib/test/sha256.pem b/Lib/test/sha256.pem --- a/Lib/test/sha256.pem +++ b/Lib/test/sha256.pem @@ -1,129 +1,128 @@ # Certificate chain for https://sha256.tbs-internet.com - 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=sha-256 production/CN=sha256.tbs-internet.com - i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC + 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=Certificats TBS X509/CN=ecom.tbs-x509.com + i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business -----BEGIN CERTIFICATE----- -MIIGXTCCBUWgAwIBAgIRAMmag+ygSAdxZsbyzYjhuW0wDQYJKoZIhvcNAQELBQAw -gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl +MIIGTjCCBTagAwIBAgIQOh3d9dNDPq1cSdJmEiMpqDANBgkqhkiG9w0BAQUFADCB +yTELMAkGA1UEBhMCRlIxETAPBgNVBAgTCENhbHZhZG9zMQ0wCwYDVQQHEwRDYWVu +MRUwEwYDVQQKEwxUQlMgSU5URVJORVQxSDBGBgNVBAsTP1Rlcm1zIGFuZCBDb25k +aXRpb25zOiBodHRwOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0EvcmVwb3NpdG9y +eTEYMBYGA1UECxMPVEJTIElOVEVSTkVUIENBMR0wGwYDVQQDExRUQlMgWDUwOSBD +QSBidXNpbmVzczAeFw0xMTAxMjUwMDAwMDBaFw0xMzAyMDUyMzU5NTlaMIHHMQsw +CQYDVQQGEwJGUjEOMAwGA1UEERMFMTQwMDAxETAPBgNVBAgTCENhbHZhZG9zMQ0w +CwYDVQQHEwRDQUVOMRswGQYDVQQJExIyMiBydWUgZGUgQnJldGFnbmUxFTATBgNV +BAoTDFRCUyBJTlRFUk5FVDEXMBUGA1UECxMOMDAwMiA0NDA0NDM4MTAxHTAbBgNV +BAsTFENlcnRpZmljYXRzIFRCUyBYNTA5MRowGAYDVQQDExFlY29tLnRicy14NTA5 +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRrlHUnJ++1lpcg +jtYco7cdmRe+EEfTmwPfCdfV3G1QfsTSvY6FfMpm/83pqHfT+4ANwr18wD9ZrAEN +G16mf9VdCGK12+TP7DmqeZyGIqlFFoahQnmb8EarvE43/1UeQ2CV9XmzwZvpqeli +LfXsFonawrY3H6ZnMwS64St61Z+9gdyuZ/RbsoZBbT5KUjDEG844QRU4OT1IGeEI +eY5NM5RNIh6ZNhVtqeeCxMS7afONkHQrOco73RdSTRck/Hj96Ofl3MHNHryr+AMK +DGFk1kLCZGpPdXtkxXvaDeQoiYDlil26CWc+YK6xyDPMdsWvoG14ZLyCpzMXA7/7 +4YAQRH0CAwEAAaOCAjAwggIsMB8GA1UdIwQYMBaAFBoJBMz5CY+7HqDO1KQUf0vV +I1jNMB0GA1UdDgQWBBQgOU8HsWzbmD4WZP5Wtdw7jca2WDAOBgNVHQ8BAf8EBAMC +BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +TAYDVR0gBEUwQzBBBgsrBgEEAYDlNwIBATAyMDAGCCsGAQUFBwIBFiRodHRwczov +L3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL0NQUzEwdwYDVR0fBHAwbjA3oDWgM4Yx +aHR0cDovL2NybC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNy +bDAzoDGgL4YtaHR0cDovL2NybC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5l +c3MuY3JsMIGwBggrBgEFBQcBAQSBozCBoDA9BggrBgEFBQcwAoYxaHR0cDovL2Ny +dC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNydDA5BggrBgEF +BQcwAoYtaHR0cDovL2NydC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5lc3Mu +Y3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wMwYDVR0R +BCwwKoIRZWNvbS50YnMteDUwOS5jb22CFXd3dy5lY29tLnRicy14NTA5LmNvbTAN +BgkqhkiG9w0BAQUFAAOCAQEArT4NHfbY87bGAw8lPV4DmHlmuDuVp/y7ltO3Ynse +3Rz8RxW2AzuO0Oy2F0Cu4yWKtMyEyMXyHqWtae7ElRbdTu5w5GwVBLJHClCzC8S9 +SpgMMQTx3Rgn8vjkHuU9VZQlulZyiPK7yunjc7c310S9FRZ7XxOwf8Nnx4WnB+No +WrfApzhhQl31w+RyrNxZe58hCfDDHmevRvwLjQ785ZoQXJDj2j3qAD4aI2yB8lB5 +oaE1jlCJzC7Kmz/Y9jzfmv/zAs1LQTm9ktevv4BTUFaGjv9jxnQ1xnS862ZiouLW +zZYIlYPf4F6JjXGiIQgQRglILUfq3ftJd9/ok9W9ZF8h8w== +-----END CERTIFICATE----- + 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business + i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root +-----BEGIN CERTIFICATE----- +MIIFPzCCBCegAwIBAgIQDlBz/++iRSmLDeVRHT/hADANBgkqhkiG9w0BAQUFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDcwOTE4MTkyMlow +gckxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -Q0EgU0dDMB4XDTEwMDIxODAwMDAwMFoXDTEyMDIxOTIzNTk1OVowgcsxCzAJBgNV -BAYTAkZSMQ4wDAYDVQQREwUxNDAwMDERMA8GA1UECBMIQ2FsdmFkb3MxDTALBgNV -BAcTBENBRU4xGzAZBgNVBAkTEjIyIHJ1ZSBkZSBCcmV0YWduZTEVMBMGA1UEChMM -VEJTIElOVEVSTkVUMRcwFQYDVQQLEw4wMDAyIDQ0MDQ0MzgxMDEbMBkGA1UECxMS -c2hhLTI1NiBwcm9kdWN0aW9uMSAwHgYDVQQDExdzaGEyNTYudGJzLWludGVybmV0 -LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbuM8VT7f0nntwu -N3F7v9KIBlhKNAxqCrziOXU5iqUt8HrQB3DtHbdmII+CpVUlwlmepsx6G+srEZ9a -MIGAy0nxi5aLb7watkyIdPjJTMvTUBQ/+RPWzt5JtYbbY9BlJ+yci0dctP74f4NU -ISLtlrEjUbf2gTohLrcE01TfmOF6PDEbB5PKDi38cB3NzKfizWfrOaJW6Q1C1qOJ -y4/4jkUREX1UFUIxzx7v62VfjXSGlcjGpBX1fvtABQOSLeE0a6gciDZs1REqroFf -5eXtqYphpTa14Z83ITXMfgg5Nze1VtMnzI9Qx4blYBw4dgQVEuIsYr7FDBOITDzc -VEVXZx0CAwEAAaOCAj8wggI7MB8GA1UdIwQYMBaAFAdEdoWTKLx/bXjSCuv6TEvf -2YIfMB0GA1UdDgQWBBSJKI/AYVI9RQNY0QPIqc8ej2QivTAOBgNVHQ8BAf8EBAMC -BaAwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIG -CisGAQQBgjcKAwMGCWCGSAGG+EIEATBMBgNVHSAERTBDMEEGCysGAQQBgOU3AgQB -MDIwMAYIKwYBBQUHAgEWJGh0dHBzOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0Ev -Q1BTNDBtBgNVHR8EZjBkMDKgMKAuhixodHRwOi8vY3JsLnRicy1pbnRlcm5ldC5j -b20vVEJTWDUwOUNBU0dDLmNybDAuoCygKoYoaHR0cDovL2NybC50YnMteDUwOS5j -b20vVEJTWDUwOUNBU0dDLmNybDCBpgYIKwYBBQUHAQEEgZkwgZYwOAYIKwYBBQUH -MAKGLGh0dHA6Ly9jcnQudGJzLWludGVybmV0LmNvbS9UQlNYNTA5Q0FTR0MuY3J0 -MDQGCCsGAQUFBzAChihodHRwOi8vY3J0LnRicy14NTA5LmNvbS9UQlNYNTA5Q0FT -R0MuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wPwYD -VR0RBDgwNoIXc2hhMjU2LnRicy1pbnRlcm5ldC5jb22CG3d3dy5zaGEyNTYudGJz -LWludGVybmV0LmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAA5NL0D4QSqhErhlkdPmz -XtiMvdGL+ZehM4coTRIpasM/Agt36Rc0NzCvnQwKE+wkngg1Gy2qe7Q0E/ziqBtB -fZYzdVgu1zdiL4kTaf+wFKYAFGsFbyeEmXysy+CMwaNoF2vpSjCU1UD56bEnTX/W -fxVZYxtBQUpnu2wOsm8cDZuZRv9XrYgAhGj9Tt6F0aVHSDGn59uwShG1+BVF/uju -SCyPTTjL1oc7YElJUzR/x4mQJYvtQI8gDIDAGEOs7v3R/gKa5EMfbUQUI4C84UbI -Yz09Jdnws/MkC/Hm1BZEqk89u7Hvfv+oHqEb0XaUo0TDfsxE0M1sMdnLb91QNQBm -UQ== ------END CERTIFICATE----- - 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC - i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root ------BEGIN CERTIFICATE----- -MIIFVjCCBD6gAwIBAgIQXpDZ0ETJMV02WTx3GTnhhTANBgkqhkiG9w0BAQUFADBv -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk -ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF -eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDYyNDE5MDYzMFow -gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl -bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u -ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -Q0EgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgOkO3f7wzN6 -rOjg45tR5vjBfzK7qmV9IBxb/QW9EEXxG+E7FNhZqQLtwGBKoSsHTnQqV75wWMk0 -9tinWvftBkSpj5sTi/8cbzJfUvTSVYh3Qxv6AVVjMMH/ruLjE6y+4PoaPs8WoYAQ -ts5R4Z1g8c/WnTepLst2x0/Wv7GmuoQi+gXvHU6YrBiu7XkeYhzc95QdviWSJRDk -owhb5K43qhcvjRmBfO/paGlCliDGZp8mHwrI21mwobWpVjTxZRwYO3bd4+TGcI4G -Ie5wmHwE8F7SK1tgSqbBacKjDa93j7txKkfz/Yd2n7TGqOXiHPsJpG655vrKtnXk -9vs1zoDeJQIDAQABo4IBljCCAZIwHQYDVR0OBBYEFAdEdoWTKLx/bXjSCuv6TEvf -2YIfMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMCAGA1UdJQQZ -MBcGCisGAQQBgjcKAwMGCWCGSAGG+EIEATAYBgNVHSAEETAPMA0GCysGAQQBgOU3 -AgQBMHsGA1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0Fk -ZFRydXN0RXh0ZXJuYWxDQVJvb3QuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9k -by5uZXQvQWRkVHJ1c3RFeHRlcm5hbENBUm9vdC5jcmwwgYAGCCsGAQUFBwEBBHQw -cjA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21vZG9jYS5jb20vQWRkVHJ1c3RV -VE5TR0NDQS5jcnQwNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvLm5ldC9B -ZGRUcnVzdFVUTlNHQ0NBLmNydDARBglghkgBhvhCAQEEBAMCAgQwDQYJKoZIhvcN -AQEFBQADggEBAK2zEzs+jcIrVK9oDkdDZNvhuBYTdCfpxfFs+OAujW0bIfJAy232 -euVsnJm6u/+OrqKudD2tad2BbejLLXhMZViaCmK7D9nrXHx4te5EP8rL19SUVqLY -1pTnv5dhNgEgvA7n5lIzDSYs7yRLsr7HJsYPr6SeYSuZizyX1SNz7ooJ32/F3X98 -RB0Mlc/E0OyOrkQ9/y5IrnpnaSora8CnUrV5XNOg+kyCz9edCyx4D5wXYcwZPVWz -8aDqquESrezPyjtfi4WRO4s/VD3HLZvOxzMrWAVYCDG9FxaOhF0QGuuG1F7F3GKV -v6prNyCl016kRl2j1UT+a7gLd8fA25A4C9E= +cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEdMBsGA1UEAxMUVEJTIFg1MDkg +Q0EgYnVzaW5lc3MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDB1PAU +qudCcz3tmyGcf+u6EkZqonKKHrV4gZYbvVkIRojmmlhfi/jwvpHvo8bqSt/9Rj5S +jhCDW0pcbI+IPPtD1Jy+CHNSfnMqVDy6CKQ3p5maTzCMG6ZT+XjnvcND5v+FtaiB +xk1iCX6uvt0jeUtdZvYbyytsSDE6c3Y5//wRxOF8tM1JxibwO3pyER26jbbN2gQz +m/EkdGjLdJ4svPk23WDAvQ6G0/z2LcAaJB+XLfqRwfQpHQvfKa1uTi8PivC8qtip +rmNQMMPMjxSK2azX8cKjjTDJiUKaCb4VHlJDWKEsCFRpgJAoAuX8f7Yfs1M4esGo +sWb3PGspK3O22uIlAgMBAAGjggF6MIIBdjAdBgNVHQ4EFgQUGgkEzPkJj7seoM7U +pBR/S9UjWM0wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwGAYD +VR0gBBEwDzANBgsrBgEEAYDlNwIBATB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8v +Y3JsLmNvbW9kb2NhLmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDA2oDSg +MoYwaHR0cDovL2NybC5jb21vZG8ubmV0L0FkZFRydXN0RXh0ZXJuYWxDQVJvb3Qu +Y3JsMIGGBggrBgEFBQcBAQR6MHgwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t +b2RvY2EuY29tL0FkZFRydXN0VVROU2VydmVyQ0EuY3J0MDkGCCsGAQUFBzAChi1o +dHRwOi8vY3J0LmNvbW9kby5uZXQvQWRkVHJ1c3RVVE5TZXJ2ZXJDQS5jcnQwEQYJ +YIZIAYb4QgEBBAQDAgIEMA0GCSqGSIb3DQEBBQUAA4IBAQA7mqrMgk/MrE6QnbNA +h4nRCn2ti4bg4w2C3lB6bSvRPnYwuNw9Jb8vuKkNFzRDxNJXqVDZdfFW5CVQJuyd +nfAx83+wk+spzvFaE1KhFYfN9G9pQfXUfvDRoIcJgPEKUXL1wRiOG+IjU3VVI8pg +IgqHkr7ylln5i5zCiFAPuIJmYUSFg/gxH5xkCNcjJqqrHrHatJr6Qrrke93joupw +oU1njfAcZtYp6fbiK6u2b1pJqwkVBE8RsfLnPhRj+SFbpvjv8Od7o/ieJhFIYQNU +k2jX2u8qZnAiNw93LZW9lpYjtuvMXq8QQppENNja5b53q7UwI+lU7ZGjZ7quuESp +J6/5 -----END CERTIFICATE----- 2 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root - i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC + i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -----BEGIN CERTIFICATE----- -MIIEZjCCA06gAwIBAgIQUSYKkxzif5zDpV954HKugjANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +MIIETzCCAzegAwIBAgIQHM5EYpUZep1jUvnyI6m2mDANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw0wNTA2MDcwODA5MTBaFw0xOTA2MjQxOTA2MzBaMG8xCzAJBgNVBAYT -AlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0 -ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB -IFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39xoz5vIABC05 -4E5b7R+8bA/Ntfojts7emxEzl6QpTH2Tn71KvJPtAxrjj8/lbVBa1pcplFqAsEl6 -2y6V/bjKvzc4LR4+kUGtcFbH8E8/6DKedMrIkFTpxl8PeJ2aQDwOrGGqXhSPnoeh -alDc15pOrwWzpnGUnHGzUGAKxxOdOAeGAqjpqGkmGJCrTLBPI6s6T4TY386f4Wlv -u9dC12tE5Met7m1BX3JacQg3s3llpFmglDf3AC8NwpJy2tA4ctsUqEXEXSp9t7TW -xO6szRNEt8kr3UMAJfphuWlqWCMRt6czj1Z1WfXNKddGtworZbbTQm8Vsrh7++/p -XVPVNFonAgMBAAGjgdgwgdUwHwYDVR0jBBgwFoAUUzLRs89/+uDxoF2FTpLSnkUd -tE8wHQYDVR0OBBYEFK29mHo0tCb3+sQmVO8DveAky1QaMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MBEGCWCGSAGG+EIBAQQEAwIBAjAgBgNVHSUEGTAX -BgorBgEEAYI3CgMDBglghkgBhvhCBAEwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDov -L2NybC51c2VydHJ1c3QuY29tL1VUTi1EQVRBQ29ycFNHQy5jcmwwDQYJKoZIhvcN -AQEFBQADggEBAMbuUxdoFLJRIh6QWA2U/b3xcOWGLcM2MY9USEbnLQg3vGwKYOEO -rVE04BKT6b64q7gmtOmWPSiPrmQH/uAB7MXjkesYoPF1ftsK5p+R26+udd8jkWjd -FwBaS/9kbHDrARrQkNnHptZt9hPk/7XJ0h4qy7ElQyZ42TCbTg0evmnv3+r+LbPM -+bDdtRTKkdSytaX7ARmjR3mfnYyVhzT4HziS2jamEfpr62vp3EV4FTkG101B5CHI -3C+H0be/SGB1pWLLJN47YaApIKa+xWycxOkKaSLvkTr6Jq/RW0GnOuL4OAdCq8Fb -+M5tug8EPzI0rNwEKNdwMBQmBsTkm5jVz3g= +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNMDUwNjA3MDgwOTEwWhcNMTkwNzA5MTgxOTIyWjBvMQswCQYD +VQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0 +IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5h +bCBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/caM+by +AAQtOeBOW+0fvGwPzbX6I7bO3psRM5ekKUx9k5+9SryT7QMa44/P5W1QWtaXKZRa +gLBJetsulf24yr83OC0ePpFBrXBWx/BPP+gynnTKyJBU6cZfD3idmkA8Dqxhql4U +j56HoWpQ3NeaTq8Fs6ZxlJxxs1BgCscTnTgHhgKo6ahpJhiQq0ywTyOrOk+E2N/O +n+Fpb7vXQtdrROTHre5tQV9yWnEIN7N5ZaRZoJQ39wAvDcKSctrQOHLbFKhFxF0q +fbe01sTurM0TRLfJK91DACX6YblpalgjEbenM49WdVn1zSnXRrcKK2W200JvFbK4 +e/vv6V1T1TRaJwIDAQABo4G9MIG6MB8GA1UdIwQYMBaAFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMB0GA1UdDgQWBBStvZh6NLQm9/rEJlTvA73gJMtUGjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAQIwRAYDVR0f +BD0wOzA5oDegNYYzaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly +c3QtSGFyZHdhcmUuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQByQhANOs4kClrwF8BW +onvUOGCSjRK52zYZgDXYNjDtmr5rJ6NyPFDNn+JxkLpjYetIFMTbSRe679Bt8m7a +gIAoQYFQtxMuyLnJegB2aEbQiIxh/tC21UcFF7ktdnDoTlA6w3pLuvunaI84Of3o +2YBrhzkTbCfaYk5JRlTpudW9DkUkHBsyx3nknPKnplkIGaK0jgn8E0n+SFabYaHk +I9LroYT/+JtLefh9lgBdAgVv0UPbzoGfuDsrk/Zh+UrgbLFpHoVnElhzbkh64Z0X +OGaJunQc68cCZu5HTn/aK7fBGMcVflRCXLVEQpU9PIAdGA8Ynvg684t8GMaKsRl1 +jIGZ -----END CERTIFICATE----- - 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC - i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC + 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware + i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -----BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -----END CERTIFICATE----- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -140,6 +140,12 @@ - Issue #14212: The re module didn't retain a reference to buffers it was scanning, resulting in segfaults. +Tests +----- + +- Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing + a test failure in test_ssl. + Build ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 03:38:37 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 03:38:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314589=3A_Update_certificate_chain_for_sha256=2Etbs-?= =?utf8?q?internet=2Ecom=2C_fixing_a?= Message-ID: http://hg.python.org/cpython/rev/34f09c654a5b changeset: 76340:34f09c654a5b parent: 76338:2df37938b8e1 parent: 76339:f323b37ef6c1 user: Antoine Pitrou date: Mon Apr 16 03:37:35 2012 +0200 summary: Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing a test failure in test_ssl. files: Lib/test/sha256.pem | 231 ++++++++++++++++--------------- Misc/NEWS | 3 + 2 files changed, 119 insertions(+), 115 deletions(-) diff --git a/Lib/test/sha256.pem b/Lib/test/sha256.pem --- a/Lib/test/sha256.pem +++ b/Lib/test/sha256.pem @@ -1,129 +1,128 @@ # Certificate chain for https://sha256.tbs-internet.com - 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=sha-256 production/CN=sha256.tbs-internet.com - i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC + 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=Certificats TBS X509/CN=ecom.tbs-x509.com + i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business -----BEGIN CERTIFICATE----- -MIIGXTCCBUWgAwIBAgIRAMmag+ygSAdxZsbyzYjhuW0wDQYJKoZIhvcNAQELBQAw -gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl +MIIGTjCCBTagAwIBAgIQOh3d9dNDPq1cSdJmEiMpqDANBgkqhkiG9w0BAQUFADCB +yTELMAkGA1UEBhMCRlIxETAPBgNVBAgTCENhbHZhZG9zMQ0wCwYDVQQHEwRDYWVu +MRUwEwYDVQQKEwxUQlMgSU5URVJORVQxSDBGBgNVBAsTP1Rlcm1zIGFuZCBDb25k +aXRpb25zOiBodHRwOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0EvcmVwb3NpdG9y +eTEYMBYGA1UECxMPVEJTIElOVEVSTkVUIENBMR0wGwYDVQQDExRUQlMgWDUwOSBD +QSBidXNpbmVzczAeFw0xMTAxMjUwMDAwMDBaFw0xMzAyMDUyMzU5NTlaMIHHMQsw +CQYDVQQGEwJGUjEOMAwGA1UEERMFMTQwMDAxETAPBgNVBAgTCENhbHZhZG9zMQ0w +CwYDVQQHEwRDQUVOMRswGQYDVQQJExIyMiBydWUgZGUgQnJldGFnbmUxFTATBgNV +BAoTDFRCUyBJTlRFUk5FVDEXMBUGA1UECxMOMDAwMiA0NDA0NDM4MTAxHTAbBgNV +BAsTFENlcnRpZmljYXRzIFRCUyBYNTA5MRowGAYDVQQDExFlY29tLnRicy14NTA5 +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRrlHUnJ++1lpcg +jtYco7cdmRe+EEfTmwPfCdfV3G1QfsTSvY6FfMpm/83pqHfT+4ANwr18wD9ZrAEN +G16mf9VdCGK12+TP7DmqeZyGIqlFFoahQnmb8EarvE43/1UeQ2CV9XmzwZvpqeli +LfXsFonawrY3H6ZnMwS64St61Z+9gdyuZ/RbsoZBbT5KUjDEG844QRU4OT1IGeEI +eY5NM5RNIh6ZNhVtqeeCxMS7afONkHQrOco73RdSTRck/Hj96Ofl3MHNHryr+AMK +DGFk1kLCZGpPdXtkxXvaDeQoiYDlil26CWc+YK6xyDPMdsWvoG14ZLyCpzMXA7/7 +4YAQRH0CAwEAAaOCAjAwggIsMB8GA1UdIwQYMBaAFBoJBMz5CY+7HqDO1KQUf0vV +I1jNMB0GA1UdDgQWBBQgOU8HsWzbmD4WZP5Wtdw7jca2WDAOBgNVHQ8BAf8EBAMC +BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +TAYDVR0gBEUwQzBBBgsrBgEEAYDlNwIBATAyMDAGCCsGAQUFBwIBFiRodHRwczov +L3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL0NQUzEwdwYDVR0fBHAwbjA3oDWgM4Yx +aHR0cDovL2NybC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNy +bDAzoDGgL4YtaHR0cDovL2NybC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5l +c3MuY3JsMIGwBggrBgEFBQcBAQSBozCBoDA9BggrBgEFBQcwAoYxaHR0cDovL2Ny +dC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNydDA5BggrBgEF +BQcwAoYtaHR0cDovL2NydC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5lc3Mu +Y3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wMwYDVR0R +BCwwKoIRZWNvbS50YnMteDUwOS5jb22CFXd3dy5lY29tLnRicy14NTA5LmNvbTAN +BgkqhkiG9w0BAQUFAAOCAQEArT4NHfbY87bGAw8lPV4DmHlmuDuVp/y7ltO3Ynse +3Rz8RxW2AzuO0Oy2F0Cu4yWKtMyEyMXyHqWtae7ElRbdTu5w5GwVBLJHClCzC8S9 +SpgMMQTx3Rgn8vjkHuU9VZQlulZyiPK7yunjc7c310S9FRZ7XxOwf8Nnx4WnB+No +WrfApzhhQl31w+RyrNxZe58hCfDDHmevRvwLjQ785ZoQXJDj2j3qAD4aI2yB8lB5 +oaE1jlCJzC7Kmz/Y9jzfmv/zAs1LQTm9ktevv4BTUFaGjv9jxnQ1xnS862ZiouLW +zZYIlYPf4F6JjXGiIQgQRglILUfq3ftJd9/ok9W9ZF8h8w== +-----END CERTIFICATE----- + 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business + i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root +-----BEGIN CERTIFICATE----- +MIIFPzCCBCegAwIBAgIQDlBz/++iRSmLDeVRHT/hADANBgkqhkiG9w0BAQUFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDcwOTE4MTkyMlow +gckxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -Q0EgU0dDMB4XDTEwMDIxODAwMDAwMFoXDTEyMDIxOTIzNTk1OVowgcsxCzAJBgNV -BAYTAkZSMQ4wDAYDVQQREwUxNDAwMDERMA8GA1UECBMIQ2FsdmFkb3MxDTALBgNV -BAcTBENBRU4xGzAZBgNVBAkTEjIyIHJ1ZSBkZSBCcmV0YWduZTEVMBMGA1UEChMM -VEJTIElOVEVSTkVUMRcwFQYDVQQLEw4wMDAyIDQ0MDQ0MzgxMDEbMBkGA1UECxMS -c2hhLTI1NiBwcm9kdWN0aW9uMSAwHgYDVQQDExdzaGEyNTYudGJzLWludGVybmV0 -LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbuM8VT7f0nntwu -N3F7v9KIBlhKNAxqCrziOXU5iqUt8HrQB3DtHbdmII+CpVUlwlmepsx6G+srEZ9a -MIGAy0nxi5aLb7watkyIdPjJTMvTUBQ/+RPWzt5JtYbbY9BlJ+yci0dctP74f4NU -ISLtlrEjUbf2gTohLrcE01TfmOF6PDEbB5PKDi38cB3NzKfizWfrOaJW6Q1C1qOJ -y4/4jkUREX1UFUIxzx7v62VfjXSGlcjGpBX1fvtABQOSLeE0a6gciDZs1REqroFf -5eXtqYphpTa14Z83ITXMfgg5Nze1VtMnzI9Qx4blYBw4dgQVEuIsYr7FDBOITDzc -VEVXZx0CAwEAAaOCAj8wggI7MB8GA1UdIwQYMBaAFAdEdoWTKLx/bXjSCuv6TEvf -2YIfMB0GA1UdDgQWBBSJKI/AYVI9RQNY0QPIqc8ej2QivTAOBgNVHQ8BAf8EBAMC -BaAwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIG -CisGAQQBgjcKAwMGCWCGSAGG+EIEATBMBgNVHSAERTBDMEEGCysGAQQBgOU3AgQB -MDIwMAYIKwYBBQUHAgEWJGh0dHBzOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0Ev -Q1BTNDBtBgNVHR8EZjBkMDKgMKAuhixodHRwOi8vY3JsLnRicy1pbnRlcm5ldC5j -b20vVEJTWDUwOUNBU0dDLmNybDAuoCygKoYoaHR0cDovL2NybC50YnMteDUwOS5j -b20vVEJTWDUwOUNBU0dDLmNybDCBpgYIKwYBBQUHAQEEgZkwgZYwOAYIKwYBBQUH -MAKGLGh0dHA6Ly9jcnQudGJzLWludGVybmV0LmNvbS9UQlNYNTA5Q0FTR0MuY3J0 -MDQGCCsGAQUFBzAChihodHRwOi8vY3J0LnRicy14NTA5LmNvbS9UQlNYNTA5Q0FT -R0MuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wPwYD -VR0RBDgwNoIXc2hhMjU2LnRicy1pbnRlcm5ldC5jb22CG3d3dy5zaGEyNTYudGJz -LWludGVybmV0LmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAA5NL0D4QSqhErhlkdPmz -XtiMvdGL+ZehM4coTRIpasM/Agt36Rc0NzCvnQwKE+wkngg1Gy2qe7Q0E/ziqBtB -fZYzdVgu1zdiL4kTaf+wFKYAFGsFbyeEmXysy+CMwaNoF2vpSjCU1UD56bEnTX/W -fxVZYxtBQUpnu2wOsm8cDZuZRv9XrYgAhGj9Tt6F0aVHSDGn59uwShG1+BVF/uju -SCyPTTjL1oc7YElJUzR/x4mQJYvtQI8gDIDAGEOs7v3R/gKa5EMfbUQUI4C84UbI -Yz09Jdnws/MkC/Hm1BZEqk89u7Hvfv+oHqEb0XaUo0TDfsxE0M1sMdnLb91QNQBm -UQ== ------END CERTIFICATE----- - 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC - i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root ------BEGIN CERTIFICATE----- -MIIFVjCCBD6gAwIBAgIQXpDZ0ETJMV02WTx3GTnhhTANBgkqhkiG9w0BAQUFADBv -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk -ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF -eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDYyNDE5MDYzMFow -gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl -bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u -ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -Q0EgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgOkO3f7wzN6 -rOjg45tR5vjBfzK7qmV9IBxb/QW9EEXxG+E7FNhZqQLtwGBKoSsHTnQqV75wWMk0 -9tinWvftBkSpj5sTi/8cbzJfUvTSVYh3Qxv6AVVjMMH/ruLjE6y+4PoaPs8WoYAQ -ts5R4Z1g8c/WnTepLst2x0/Wv7GmuoQi+gXvHU6YrBiu7XkeYhzc95QdviWSJRDk -owhb5K43qhcvjRmBfO/paGlCliDGZp8mHwrI21mwobWpVjTxZRwYO3bd4+TGcI4G -Ie5wmHwE8F7SK1tgSqbBacKjDa93j7txKkfz/Yd2n7TGqOXiHPsJpG655vrKtnXk -9vs1zoDeJQIDAQABo4IBljCCAZIwHQYDVR0OBBYEFAdEdoWTKLx/bXjSCuv6TEvf -2YIfMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMCAGA1UdJQQZ -MBcGCisGAQQBgjcKAwMGCWCGSAGG+EIEATAYBgNVHSAEETAPMA0GCysGAQQBgOU3 -AgQBMHsGA1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0Fk -ZFRydXN0RXh0ZXJuYWxDQVJvb3QuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9k -by5uZXQvQWRkVHJ1c3RFeHRlcm5hbENBUm9vdC5jcmwwgYAGCCsGAQUFBwEBBHQw -cjA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21vZG9jYS5jb20vQWRkVHJ1c3RV -VE5TR0NDQS5jcnQwNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvLm5ldC9B -ZGRUcnVzdFVUTlNHQ0NBLmNydDARBglghkgBhvhCAQEEBAMCAgQwDQYJKoZIhvcN -AQEFBQADggEBAK2zEzs+jcIrVK9oDkdDZNvhuBYTdCfpxfFs+OAujW0bIfJAy232 -euVsnJm6u/+OrqKudD2tad2BbejLLXhMZViaCmK7D9nrXHx4te5EP8rL19SUVqLY -1pTnv5dhNgEgvA7n5lIzDSYs7yRLsr7HJsYPr6SeYSuZizyX1SNz7ooJ32/F3X98 -RB0Mlc/E0OyOrkQ9/y5IrnpnaSora8CnUrV5XNOg+kyCz9edCyx4D5wXYcwZPVWz -8aDqquESrezPyjtfi4WRO4s/VD3HLZvOxzMrWAVYCDG9FxaOhF0QGuuG1F7F3GKV -v6prNyCl016kRl2j1UT+a7gLd8fA25A4C9E= +cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEdMBsGA1UEAxMUVEJTIFg1MDkg +Q0EgYnVzaW5lc3MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDB1PAU +qudCcz3tmyGcf+u6EkZqonKKHrV4gZYbvVkIRojmmlhfi/jwvpHvo8bqSt/9Rj5S +jhCDW0pcbI+IPPtD1Jy+CHNSfnMqVDy6CKQ3p5maTzCMG6ZT+XjnvcND5v+FtaiB +xk1iCX6uvt0jeUtdZvYbyytsSDE6c3Y5//wRxOF8tM1JxibwO3pyER26jbbN2gQz +m/EkdGjLdJ4svPk23WDAvQ6G0/z2LcAaJB+XLfqRwfQpHQvfKa1uTi8PivC8qtip +rmNQMMPMjxSK2azX8cKjjTDJiUKaCb4VHlJDWKEsCFRpgJAoAuX8f7Yfs1M4esGo +sWb3PGspK3O22uIlAgMBAAGjggF6MIIBdjAdBgNVHQ4EFgQUGgkEzPkJj7seoM7U +pBR/S9UjWM0wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwGAYD +VR0gBBEwDzANBgsrBgEEAYDlNwIBATB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8v +Y3JsLmNvbW9kb2NhLmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDA2oDSg +MoYwaHR0cDovL2NybC5jb21vZG8ubmV0L0FkZFRydXN0RXh0ZXJuYWxDQVJvb3Qu +Y3JsMIGGBggrBgEFBQcBAQR6MHgwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t +b2RvY2EuY29tL0FkZFRydXN0VVROU2VydmVyQ0EuY3J0MDkGCCsGAQUFBzAChi1o +dHRwOi8vY3J0LmNvbW9kby5uZXQvQWRkVHJ1c3RVVE5TZXJ2ZXJDQS5jcnQwEQYJ +YIZIAYb4QgEBBAQDAgIEMA0GCSqGSIb3DQEBBQUAA4IBAQA7mqrMgk/MrE6QnbNA +h4nRCn2ti4bg4w2C3lB6bSvRPnYwuNw9Jb8vuKkNFzRDxNJXqVDZdfFW5CVQJuyd +nfAx83+wk+spzvFaE1KhFYfN9G9pQfXUfvDRoIcJgPEKUXL1wRiOG+IjU3VVI8pg +IgqHkr7ylln5i5zCiFAPuIJmYUSFg/gxH5xkCNcjJqqrHrHatJr6Qrrke93joupw +oU1njfAcZtYp6fbiK6u2b1pJqwkVBE8RsfLnPhRj+SFbpvjv8Od7o/ieJhFIYQNU +k2jX2u8qZnAiNw93LZW9lpYjtuvMXq8QQppENNja5b53q7UwI+lU7ZGjZ7quuESp +J6/5 -----END CERTIFICATE----- 2 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root - i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC + i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -----BEGIN CERTIFICATE----- -MIIEZjCCA06gAwIBAgIQUSYKkxzif5zDpV954HKugjANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +MIIETzCCAzegAwIBAgIQHM5EYpUZep1jUvnyI6m2mDANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw0wNTA2MDcwODA5MTBaFw0xOTA2MjQxOTA2MzBaMG8xCzAJBgNVBAYT -AlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0 -ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB -IFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39xoz5vIABC05 -4E5b7R+8bA/Ntfojts7emxEzl6QpTH2Tn71KvJPtAxrjj8/lbVBa1pcplFqAsEl6 -2y6V/bjKvzc4LR4+kUGtcFbH8E8/6DKedMrIkFTpxl8PeJ2aQDwOrGGqXhSPnoeh -alDc15pOrwWzpnGUnHGzUGAKxxOdOAeGAqjpqGkmGJCrTLBPI6s6T4TY386f4Wlv -u9dC12tE5Met7m1BX3JacQg3s3llpFmglDf3AC8NwpJy2tA4ctsUqEXEXSp9t7TW -xO6szRNEt8kr3UMAJfphuWlqWCMRt6czj1Z1WfXNKddGtworZbbTQm8Vsrh7++/p -XVPVNFonAgMBAAGjgdgwgdUwHwYDVR0jBBgwFoAUUzLRs89/+uDxoF2FTpLSnkUd -tE8wHQYDVR0OBBYEFK29mHo0tCb3+sQmVO8DveAky1QaMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MBEGCWCGSAGG+EIBAQQEAwIBAjAgBgNVHSUEGTAX -BgorBgEEAYI3CgMDBglghkgBhvhCBAEwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDov -L2NybC51c2VydHJ1c3QuY29tL1VUTi1EQVRBQ29ycFNHQy5jcmwwDQYJKoZIhvcN -AQEFBQADggEBAMbuUxdoFLJRIh6QWA2U/b3xcOWGLcM2MY9USEbnLQg3vGwKYOEO -rVE04BKT6b64q7gmtOmWPSiPrmQH/uAB7MXjkesYoPF1ftsK5p+R26+udd8jkWjd -FwBaS/9kbHDrARrQkNnHptZt9hPk/7XJ0h4qy7ElQyZ42TCbTg0evmnv3+r+LbPM -+bDdtRTKkdSytaX7ARmjR3mfnYyVhzT4HziS2jamEfpr62vp3EV4FTkG101B5CHI -3C+H0be/SGB1pWLLJN47YaApIKa+xWycxOkKaSLvkTr6Jq/RW0GnOuL4OAdCq8Fb -+M5tug8EPzI0rNwEKNdwMBQmBsTkm5jVz3g= +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNMDUwNjA3MDgwOTEwWhcNMTkwNzA5MTgxOTIyWjBvMQswCQYD +VQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0 +IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5h +bCBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/caM+by +AAQtOeBOW+0fvGwPzbX6I7bO3psRM5ekKUx9k5+9SryT7QMa44/P5W1QWtaXKZRa +gLBJetsulf24yr83OC0ePpFBrXBWx/BPP+gynnTKyJBU6cZfD3idmkA8Dqxhql4U +j56HoWpQ3NeaTq8Fs6ZxlJxxs1BgCscTnTgHhgKo6ahpJhiQq0ywTyOrOk+E2N/O +n+Fpb7vXQtdrROTHre5tQV9yWnEIN7N5ZaRZoJQ39wAvDcKSctrQOHLbFKhFxF0q +fbe01sTurM0TRLfJK91DACX6YblpalgjEbenM49WdVn1zSnXRrcKK2W200JvFbK4 +e/vv6V1T1TRaJwIDAQABo4G9MIG6MB8GA1UdIwQYMBaAFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMB0GA1UdDgQWBBStvZh6NLQm9/rEJlTvA73gJMtUGjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAQIwRAYDVR0f +BD0wOzA5oDegNYYzaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly +c3QtSGFyZHdhcmUuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQByQhANOs4kClrwF8BW +onvUOGCSjRK52zYZgDXYNjDtmr5rJ6NyPFDNn+JxkLpjYetIFMTbSRe679Bt8m7a +gIAoQYFQtxMuyLnJegB2aEbQiIxh/tC21UcFF7ktdnDoTlA6w3pLuvunaI84Of3o +2YBrhzkTbCfaYk5JRlTpudW9DkUkHBsyx3nknPKnplkIGaK0jgn8E0n+SFabYaHk +I9LroYT/+JtLefh9lgBdAgVv0UPbzoGfuDsrk/Zh+UrgbLFpHoVnElhzbkh64Z0X +OGaJunQc68cCZu5HTn/aK7fBGMcVflRCXLVEQpU9PIAdGA8Ynvg684t8GMaKsRl1 +jIGZ -----END CERTIFICATE----- - 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC - i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC + 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware + i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -----BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -----END CERTIFICATE----- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -90,6 +90,9 @@ Tests ----- +- Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing + a test failure in test_ssl. + - Issue #14355: Regrtest now supports the standard unittest test loading, and will use it if a test file contains no `test_main` method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 03:40:31 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 03:40:31 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NTg5?= =?utf8?q?=3A_Update_certificate_chain_for_sha256=2Etbs-internet=2Ecom=2C_?= =?utf8?q?fixing_a?= Message-ID: http://hg.python.org/cpython/rev/33bc53e0aa9e changeset: 76341:33bc53e0aa9e branch: 2.7 parent: 76326:bfe2d1acc09d user: Antoine Pitrou date: Mon Apr 16 03:34:44 2012 +0200 summary: Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing a test failure in test_ssl. files: Lib/test/sha256.pem | 231 ++++++++++++++++--------------- Misc/NEWS | 6 + 2 files changed, 122 insertions(+), 115 deletions(-) diff --git a/Lib/test/sha256.pem b/Lib/test/sha256.pem --- a/Lib/test/sha256.pem +++ b/Lib/test/sha256.pem @@ -1,129 +1,128 @@ # Certificate chain for https://sha256.tbs-internet.com - 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=sha-256 production/CN=sha256.tbs-internet.com - i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC + 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=Certificats TBS X509/CN=ecom.tbs-x509.com + i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business -----BEGIN CERTIFICATE----- -MIIGXTCCBUWgAwIBAgIRAMmag+ygSAdxZsbyzYjhuW0wDQYJKoZIhvcNAQELBQAw -gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl +MIIGTjCCBTagAwIBAgIQOh3d9dNDPq1cSdJmEiMpqDANBgkqhkiG9w0BAQUFADCB +yTELMAkGA1UEBhMCRlIxETAPBgNVBAgTCENhbHZhZG9zMQ0wCwYDVQQHEwRDYWVu +MRUwEwYDVQQKEwxUQlMgSU5URVJORVQxSDBGBgNVBAsTP1Rlcm1zIGFuZCBDb25k +aXRpb25zOiBodHRwOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0EvcmVwb3NpdG9y +eTEYMBYGA1UECxMPVEJTIElOVEVSTkVUIENBMR0wGwYDVQQDExRUQlMgWDUwOSBD +QSBidXNpbmVzczAeFw0xMTAxMjUwMDAwMDBaFw0xMzAyMDUyMzU5NTlaMIHHMQsw +CQYDVQQGEwJGUjEOMAwGA1UEERMFMTQwMDAxETAPBgNVBAgTCENhbHZhZG9zMQ0w +CwYDVQQHEwRDQUVOMRswGQYDVQQJExIyMiBydWUgZGUgQnJldGFnbmUxFTATBgNV +BAoTDFRCUyBJTlRFUk5FVDEXMBUGA1UECxMOMDAwMiA0NDA0NDM4MTAxHTAbBgNV +BAsTFENlcnRpZmljYXRzIFRCUyBYNTA5MRowGAYDVQQDExFlY29tLnRicy14NTA5 +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRrlHUnJ++1lpcg +jtYco7cdmRe+EEfTmwPfCdfV3G1QfsTSvY6FfMpm/83pqHfT+4ANwr18wD9ZrAEN +G16mf9VdCGK12+TP7DmqeZyGIqlFFoahQnmb8EarvE43/1UeQ2CV9XmzwZvpqeli +LfXsFonawrY3H6ZnMwS64St61Z+9gdyuZ/RbsoZBbT5KUjDEG844QRU4OT1IGeEI +eY5NM5RNIh6ZNhVtqeeCxMS7afONkHQrOco73RdSTRck/Hj96Ofl3MHNHryr+AMK +DGFk1kLCZGpPdXtkxXvaDeQoiYDlil26CWc+YK6xyDPMdsWvoG14ZLyCpzMXA7/7 +4YAQRH0CAwEAAaOCAjAwggIsMB8GA1UdIwQYMBaAFBoJBMz5CY+7HqDO1KQUf0vV +I1jNMB0GA1UdDgQWBBQgOU8HsWzbmD4WZP5Wtdw7jca2WDAOBgNVHQ8BAf8EBAMC +BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +TAYDVR0gBEUwQzBBBgsrBgEEAYDlNwIBATAyMDAGCCsGAQUFBwIBFiRodHRwczov +L3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL0NQUzEwdwYDVR0fBHAwbjA3oDWgM4Yx +aHR0cDovL2NybC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNy +bDAzoDGgL4YtaHR0cDovL2NybC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5l +c3MuY3JsMIGwBggrBgEFBQcBAQSBozCBoDA9BggrBgEFBQcwAoYxaHR0cDovL2Ny +dC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNydDA5BggrBgEF +BQcwAoYtaHR0cDovL2NydC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5lc3Mu +Y3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wMwYDVR0R +BCwwKoIRZWNvbS50YnMteDUwOS5jb22CFXd3dy5lY29tLnRicy14NTA5LmNvbTAN +BgkqhkiG9w0BAQUFAAOCAQEArT4NHfbY87bGAw8lPV4DmHlmuDuVp/y7ltO3Ynse +3Rz8RxW2AzuO0Oy2F0Cu4yWKtMyEyMXyHqWtae7ElRbdTu5w5GwVBLJHClCzC8S9 +SpgMMQTx3Rgn8vjkHuU9VZQlulZyiPK7yunjc7c310S9FRZ7XxOwf8Nnx4WnB+No +WrfApzhhQl31w+RyrNxZe58hCfDDHmevRvwLjQ785ZoQXJDj2j3qAD4aI2yB8lB5 +oaE1jlCJzC7Kmz/Y9jzfmv/zAs1LQTm9ktevv4BTUFaGjv9jxnQ1xnS862ZiouLW +zZYIlYPf4F6JjXGiIQgQRglILUfq3ftJd9/ok9W9ZF8h8w== +-----END CERTIFICATE----- + 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business + i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root +-----BEGIN CERTIFICATE----- +MIIFPzCCBCegAwIBAgIQDlBz/++iRSmLDeVRHT/hADANBgkqhkiG9w0BAQUFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDcwOTE4MTkyMlow +gckxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -Q0EgU0dDMB4XDTEwMDIxODAwMDAwMFoXDTEyMDIxOTIzNTk1OVowgcsxCzAJBgNV -BAYTAkZSMQ4wDAYDVQQREwUxNDAwMDERMA8GA1UECBMIQ2FsdmFkb3MxDTALBgNV -BAcTBENBRU4xGzAZBgNVBAkTEjIyIHJ1ZSBkZSBCcmV0YWduZTEVMBMGA1UEChMM -VEJTIElOVEVSTkVUMRcwFQYDVQQLEw4wMDAyIDQ0MDQ0MzgxMDEbMBkGA1UECxMS -c2hhLTI1NiBwcm9kdWN0aW9uMSAwHgYDVQQDExdzaGEyNTYudGJzLWludGVybmV0 -LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbuM8VT7f0nntwu -N3F7v9KIBlhKNAxqCrziOXU5iqUt8HrQB3DtHbdmII+CpVUlwlmepsx6G+srEZ9a -MIGAy0nxi5aLb7watkyIdPjJTMvTUBQ/+RPWzt5JtYbbY9BlJ+yci0dctP74f4NU -ISLtlrEjUbf2gTohLrcE01TfmOF6PDEbB5PKDi38cB3NzKfizWfrOaJW6Q1C1qOJ -y4/4jkUREX1UFUIxzx7v62VfjXSGlcjGpBX1fvtABQOSLeE0a6gciDZs1REqroFf -5eXtqYphpTa14Z83ITXMfgg5Nze1VtMnzI9Qx4blYBw4dgQVEuIsYr7FDBOITDzc -VEVXZx0CAwEAAaOCAj8wggI7MB8GA1UdIwQYMBaAFAdEdoWTKLx/bXjSCuv6TEvf -2YIfMB0GA1UdDgQWBBSJKI/AYVI9RQNY0QPIqc8ej2QivTAOBgNVHQ8BAf8EBAMC -BaAwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIG -CisGAQQBgjcKAwMGCWCGSAGG+EIEATBMBgNVHSAERTBDMEEGCysGAQQBgOU3AgQB -MDIwMAYIKwYBBQUHAgEWJGh0dHBzOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0Ev -Q1BTNDBtBgNVHR8EZjBkMDKgMKAuhixodHRwOi8vY3JsLnRicy1pbnRlcm5ldC5j -b20vVEJTWDUwOUNBU0dDLmNybDAuoCygKoYoaHR0cDovL2NybC50YnMteDUwOS5j -b20vVEJTWDUwOUNBU0dDLmNybDCBpgYIKwYBBQUHAQEEgZkwgZYwOAYIKwYBBQUH -MAKGLGh0dHA6Ly9jcnQudGJzLWludGVybmV0LmNvbS9UQlNYNTA5Q0FTR0MuY3J0 -MDQGCCsGAQUFBzAChihodHRwOi8vY3J0LnRicy14NTA5LmNvbS9UQlNYNTA5Q0FT -R0MuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wPwYD -VR0RBDgwNoIXc2hhMjU2LnRicy1pbnRlcm5ldC5jb22CG3d3dy5zaGEyNTYudGJz -LWludGVybmV0LmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAA5NL0D4QSqhErhlkdPmz -XtiMvdGL+ZehM4coTRIpasM/Agt36Rc0NzCvnQwKE+wkngg1Gy2qe7Q0E/ziqBtB -fZYzdVgu1zdiL4kTaf+wFKYAFGsFbyeEmXysy+CMwaNoF2vpSjCU1UD56bEnTX/W -fxVZYxtBQUpnu2wOsm8cDZuZRv9XrYgAhGj9Tt6F0aVHSDGn59uwShG1+BVF/uju -SCyPTTjL1oc7YElJUzR/x4mQJYvtQI8gDIDAGEOs7v3R/gKa5EMfbUQUI4C84UbI -Yz09Jdnws/MkC/Hm1BZEqk89u7Hvfv+oHqEb0XaUo0TDfsxE0M1sMdnLb91QNQBm -UQ== ------END CERTIFICATE----- - 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC - i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root ------BEGIN CERTIFICATE----- -MIIFVjCCBD6gAwIBAgIQXpDZ0ETJMV02WTx3GTnhhTANBgkqhkiG9w0BAQUFADBv -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk -ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF -eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDYyNDE5MDYzMFow -gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl -bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u -ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -Q0EgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgOkO3f7wzN6 -rOjg45tR5vjBfzK7qmV9IBxb/QW9EEXxG+E7FNhZqQLtwGBKoSsHTnQqV75wWMk0 -9tinWvftBkSpj5sTi/8cbzJfUvTSVYh3Qxv6AVVjMMH/ruLjE6y+4PoaPs8WoYAQ -ts5R4Z1g8c/WnTepLst2x0/Wv7GmuoQi+gXvHU6YrBiu7XkeYhzc95QdviWSJRDk -owhb5K43qhcvjRmBfO/paGlCliDGZp8mHwrI21mwobWpVjTxZRwYO3bd4+TGcI4G -Ie5wmHwE8F7SK1tgSqbBacKjDa93j7txKkfz/Yd2n7TGqOXiHPsJpG655vrKtnXk -9vs1zoDeJQIDAQABo4IBljCCAZIwHQYDVR0OBBYEFAdEdoWTKLx/bXjSCuv6TEvf -2YIfMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMCAGA1UdJQQZ -MBcGCisGAQQBgjcKAwMGCWCGSAGG+EIEATAYBgNVHSAEETAPMA0GCysGAQQBgOU3 -AgQBMHsGA1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0Fk -ZFRydXN0RXh0ZXJuYWxDQVJvb3QuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9k -by5uZXQvQWRkVHJ1c3RFeHRlcm5hbENBUm9vdC5jcmwwgYAGCCsGAQUFBwEBBHQw -cjA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21vZG9jYS5jb20vQWRkVHJ1c3RV -VE5TR0NDQS5jcnQwNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvLm5ldC9B -ZGRUcnVzdFVUTlNHQ0NBLmNydDARBglghkgBhvhCAQEEBAMCAgQwDQYJKoZIhvcN -AQEFBQADggEBAK2zEzs+jcIrVK9oDkdDZNvhuBYTdCfpxfFs+OAujW0bIfJAy232 -euVsnJm6u/+OrqKudD2tad2BbejLLXhMZViaCmK7D9nrXHx4te5EP8rL19SUVqLY -1pTnv5dhNgEgvA7n5lIzDSYs7yRLsr7HJsYPr6SeYSuZizyX1SNz7ooJ32/F3X98 -RB0Mlc/E0OyOrkQ9/y5IrnpnaSora8CnUrV5XNOg+kyCz9edCyx4D5wXYcwZPVWz -8aDqquESrezPyjtfi4WRO4s/VD3HLZvOxzMrWAVYCDG9FxaOhF0QGuuG1F7F3GKV -v6prNyCl016kRl2j1UT+a7gLd8fA25A4C9E= +cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEdMBsGA1UEAxMUVEJTIFg1MDkg +Q0EgYnVzaW5lc3MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDB1PAU +qudCcz3tmyGcf+u6EkZqonKKHrV4gZYbvVkIRojmmlhfi/jwvpHvo8bqSt/9Rj5S +jhCDW0pcbI+IPPtD1Jy+CHNSfnMqVDy6CKQ3p5maTzCMG6ZT+XjnvcND5v+FtaiB +xk1iCX6uvt0jeUtdZvYbyytsSDE6c3Y5//wRxOF8tM1JxibwO3pyER26jbbN2gQz +m/EkdGjLdJ4svPk23WDAvQ6G0/z2LcAaJB+XLfqRwfQpHQvfKa1uTi8PivC8qtip +rmNQMMPMjxSK2azX8cKjjTDJiUKaCb4VHlJDWKEsCFRpgJAoAuX8f7Yfs1M4esGo +sWb3PGspK3O22uIlAgMBAAGjggF6MIIBdjAdBgNVHQ4EFgQUGgkEzPkJj7seoM7U +pBR/S9UjWM0wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwGAYD +VR0gBBEwDzANBgsrBgEEAYDlNwIBATB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8v +Y3JsLmNvbW9kb2NhLmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDA2oDSg +MoYwaHR0cDovL2NybC5jb21vZG8ubmV0L0FkZFRydXN0RXh0ZXJuYWxDQVJvb3Qu +Y3JsMIGGBggrBgEFBQcBAQR6MHgwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t +b2RvY2EuY29tL0FkZFRydXN0VVROU2VydmVyQ0EuY3J0MDkGCCsGAQUFBzAChi1o +dHRwOi8vY3J0LmNvbW9kby5uZXQvQWRkVHJ1c3RVVE5TZXJ2ZXJDQS5jcnQwEQYJ +YIZIAYb4QgEBBAQDAgIEMA0GCSqGSIb3DQEBBQUAA4IBAQA7mqrMgk/MrE6QnbNA +h4nRCn2ti4bg4w2C3lB6bSvRPnYwuNw9Jb8vuKkNFzRDxNJXqVDZdfFW5CVQJuyd +nfAx83+wk+spzvFaE1KhFYfN9G9pQfXUfvDRoIcJgPEKUXL1wRiOG+IjU3VVI8pg +IgqHkr7ylln5i5zCiFAPuIJmYUSFg/gxH5xkCNcjJqqrHrHatJr6Qrrke93joupw +oU1njfAcZtYp6fbiK6u2b1pJqwkVBE8RsfLnPhRj+SFbpvjv8Od7o/ieJhFIYQNU +k2jX2u8qZnAiNw93LZW9lpYjtuvMXq8QQppENNja5b53q7UwI+lU7ZGjZ7quuESp +J6/5 -----END CERTIFICATE----- 2 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root - i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC + i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -----BEGIN CERTIFICATE----- -MIIEZjCCA06gAwIBAgIQUSYKkxzif5zDpV954HKugjANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +MIIETzCCAzegAwIBAgIQHM5EYpUZep1jUvnyI6m2mDANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw0wNTA2MDcwODA5MTBaFw0xOTA2MjQxOTA2MzBaMG8xCzAJBgNVBAYT -AlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0 -ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB -IFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39xoz5vIABC05 -4E5b7R+8bA/Ntfojts7emxEzl6QpTH2Tn71KvJPtAxrjj8/lbVBa1pcplFqAsEl6 -2y6V/bjKvzc4LR4+kUGtcFbH8E8/6DKedMrIkFTpxl8PeJ2aQDwOrGGqXhSPnoeh -alDc15pOrwWzpnGUnHGzUGAKxxOdOAeGAqjpqGkmGJCrTLBPI6s6T4TY386f4Wlv -u9dC12tE5Met7m1BX3JacQg3s3llpFmglDf3AC8NwpJy2tA4ctsUqEXEXSp9t7TW -xO6szRNEt8kr3UMAJfphuWlqWCMRt6czj1Z1WfXNKddGtworZbbTQm8Vsrh7++/p -XVPVNFonAgMBAAGjgdgwgdUwHwYDVR0jBBgwFoAUUzLRs89/+uDxoF2FTpLSnkUd -tE8wHQYDVR0OBBYEFK29mHo0tCb3+sQmVO8DveAky1QaMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MBEGCWCGSAGG+EIBAQQEAwIBAjAgBgNVHSUEGTAX -BgorBgEEAYI3CgMDBglghkgBhvhCBAEwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDov -L2NybC51c2VydHJ1c3QuY29tL1VUTi1EQVRBQ29ycFNHQy5jcmwwDQYJKoZIhvcN -AQEFBQADggEBAMbuUxdoFLJRIh6QWA2U/b3xcOWGLcM2MY9USEbnLQg3vGwKYOEO -rVE04BKT6b64q7gmtOmWPSiPrmQH/uAB7MXjkesYoPF1ftsK5p+R26+udd8jkWjd -FwBaS/9kbHDrARrQkNnHptZt9hPk/7XJ0h4qy7ElQyZ42TCbTg0evmnv3+r+LbPM -+bDdtRTKkdSytaX7ARmjR3mfnYyVhzT4HziS2jamEfpr62vp3EV4FTkG101B5CHI -3C+H0be/SGB1pWLLJN47YaApIKa+xWycxOkKaSLvkTr6Jq/RW0GnOuL4OAdCq8Fb -+M5tug8EPzI0rNwEKNdwMBQmBsTkm5jVz3g= +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNMDUwNjA3MDgwOTEwWhcNMTkwNzA5MTgxOTIyWjBvMQswCQYD +VQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0 +IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5h +bCBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/caM+by +AAQtOeBOW+0fvGwPzbX6I7bO3psRM5ekKUx9k5+9SryT7QMa44/P5W1QWtaXKZRa +gLBJetsulf24yr83OC0ePpFBrXBWx/BPP+gynnTKyJBU6cZfD3idmkA8Dqxhql4U +j56HoWpQ3NeaTq8Fs6ZxlJxxs1BgCscTnTgHhgKo6ahpJhiQq0ywTyOrOk+E2N/O +n+Fpb7vXQtdrROTHre5tQV9yWnEIN7N5ZaRZoJQ39wAvDcKSctrQOHLbFKhFxF0q +fbe01sTurM0TRLfJK91DACX6YblpalgjEbenM49WdVn1zSnXRrcKK2W200JvFbK4 +e/vv6V1T1TRaJwIDAQABo4G9MIG6MB8GA1UdIwQYMBaAFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMB0GA1UdDgQWBBStvZh6NLQm9/rEJlTvA73gJMtUGjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAQIwRAYDVR0f +BD0wOzA5oDegNYYzaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly +c3QtSGFyZHdhcmUuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQByQhANOs4kClrwF8BW +onvUOGCSjRK52zYZgDXYNjDtmr5rJ6NyPFDNn+JxkLpjYetIFMTbSRe679Bt8m7a +gIAoQYFQtxMuyLnJegB2aEbQiIxh/tC21UcFF7ktdnDoTlA6w3pLuvunaI84Of3o +2YBrhzkTbCfaYk5JRlTpudW9DkUkHBsyx3nknPKnplkIGaK0jgn8E0n+SFabYaHk +I9LroYT/+JtLefh9lgBdAgVv0UPbzoGfuDsrk/Zh+UrgbLFpHoVnElhzbkh64Z0X +OGaJunQc68cCZu5HTn/aK7fBGMcVflRCXLVEQpU9PIAdGA8Ynvg684t8GMaKsRl1 +jIGZ -----END CERTIFICATE----- - 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC - i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC + 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware + i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -----BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -----END CERTIFICATE----- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -102,6 +102,12 @@ - Issue #6884: Fix long-standing bugs with MANIFEST.in parsing in distutils on Windows. +Tests +----- + +- Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing + a test failure in test_ssl. + Build ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 04:28:59 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 16 Apr 2012 04:28:59 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Re-implem?= =?utf8?b?ZW50IGltcC5sb2FkX3BhY2thZ2UoKSBpbiBpbXAucHku?= Message-ID: http://hg.python.org/cpython/rev/4256df44023b changeset: 76342:4256df44023b parent: 76338:2df37938b8e1 user: Brett Cannon date: Sun Apr 15 22:28:28 2012 -0400 summary: Issue #13959: Re-implement imp.load_package() in imp.py. Thanks to Eric Snow for helping with imp.load_module() (previous commit) which led to the removal of a bunch of C code. files: Lib/imp.py | 19 +++- Python/import.c | 171 ------------------------------------ 2 files changed, 17 insertions(+), 173 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -14,14 +14,29 @@ from _imp import (get_magic, get_tag, get_suffixes, cache_from_source, source_from_cache) # Should be re-implemented here (and mostly deprecated) -from _imp import (find_module, load_compiled, - load_package, load_source, NullImporter, +from _imp import (find_module, load_compiled, load_source, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, PY_CODERESOURCE, IMP_HOOK) from importlib._bootstrap import _new_module as new_module +from importlib import _bootstrap +import os + + +def load_package(name, path): + if os.path.isdir(path): + extensions = _bootstrap._suffix_list(PY_SOURCE) + extensions += _bootstrap._suffix_list(PY_COMPILED) + for extension in extensions: + path = os.path.join(path, '__init__'+extension) + if os.path.exists(path): + break + else: + raise ValueError('{!r} is not a package'.format(path)) + return _bootstrap._SourceFileLoader(name, path).load_module(name) + def load_module(name, file, filename, details): """Load a module, given information returned by find_module(). diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1602,65 +1602,10 @@ } /* Forward */ -static PyObject *load_module(PyObject *, FILE *, PyObject *, int, PyObject *); static struct filedescr *find_module(PyObject *, PyObject *, PyObject *, PyObject **, FILE **, PyObject **); static struct _frozen * find_frozen(PyObject *); -/* Load a package and return its module object WITH INCREMENTED - REFERENCE COUNT */ - -static PyObject * -load_package(PyObject *name, PyObject *pathname) -{ - PyObject *m, *d, *bufobj; - PyObject *file = NULL, *path_list = NULL; - int err; - FILE *fp = NULL; - struct filedescr *fdp; - - m = PyImport_AddModuleObject(name); - if (m == NULL) - return NULL; - if (Py_VerboseFlag) - PySys_FormatStderr("import %U # directory %R\n", - name, pathname); - file = get_sourcefile(pathname); - if (file == NULL) - return NULL; - path_list = Py_BuildValue("[O]", file); - if (path_list == NULL) { - Py_DECREF(file); - return NULL; - } - d = PyModule_GetDict(m); - err = PyDict_SetItemString(d, "__file__", file); - Py_DECREF(file); - if (err == 0) - err = PyDict_SetItemString(d, "__path__", path_list); - if (err != 0) { - Py_DECREF(path_list); - return NULL; - } - fdp = find_module(name, initstr, path_list, - &bufobj, &fp, NULL); - Py_DECREF(path_list); - if (fdp == NULL) { - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - PyErr_Clear(); - Py_INCREF(m); - return m; - } - else - return NULL; - } - m = load_module(name, fp, bufobj, fdp->type, NULL); - Py_XDECREF(bufobj); - if (fp != NULL) - fclose(fp); - return m; -} - /* Helper to test for built-in module */ @@ -2434,108 +2379,6 @@ static int init_builtin(PyObject *); /* Forward */ -static PyObject* -load_builtin(PyObject *name, int type) -{ - PyObject *m, *modules; - int err; - - if (type == C_BUILTIN) - err = init_builtin(name); - else - err = PyImport_ImportFrozenModuleObject(name); - if (err < 0) - return NULL; - if (err == 0) { - PyErr_Format(PyExc_ImportError, - "Purported %s module %R not found", - type == C_BUILTIN ? "builtin" : "frozen", - name); - return NULL; - } - - modules = PyImport_GetModuleDict(); - m = PyDict_GetItem(modules, name); - if (m == NULL) { - PyErr_Format( - PyExc_ImportError, - "%s module %R not properly initialized", - type == C_BUILTIN ? "builtin" : "frozen", - name); - return NULL; - } - Py_INCREF(m); - return m; -} - -/* Load an external module using the default search path and return - its module object WITH INCREMENTED REFERENCE COUNT */ - -static PyObject * -load_module(PyObject *name, FILE *fp, PyObject *pathname, int type, PyObject *loader) -{ - PyObject *m; - - /* First check that there's an open file (if we need one) */ - switch (type) { - case PY_SOURCE: - case PY_COMPILED: - if (fp == NULL) { - PyErr_Format(PyExc_ValueError, - "file object required for import (type code %d)", - type); - return NULL; - } - } - - switch (type) { - - case PY_SOURCE: - m = load_source_module(name, pathname, fp); - break; - - case PY_COMPILED: - m = load_compiled_module(name, pathname, fp); - break; - -#ifdef HAVE_DYNAMIC_LOADING - case C_EXTENSION: - m = _PyImport_LoadDynamicModule(name, pathname, fp); - break; -#endif - - case PKG_DIRECTORY: - m = load_package(name, pathname); - break; - - case C_BUILTIN: - case PY_FROZEN: - m = load_builtin(name, type); - break; - - case IMP_HOOK: { - _Py_IDENTIFIER(load_module); - if (loader == NULL) { - PyErr_SetString(PyExc_ImportError, - "import hook without loader"); - return NULL; - } - m = _PyObject_CallMethodId(loader, &PyId_load_module, "O", name); - break; - } - - default: - PyErr_Format(PyExc_ImportError, - "Don't know how to import %R (type code %d)", - name, type); - m = NULL; - - } - - return m; -} - - /* Initialize a built-in module. Return 1 for success, 0 if the module is not found, and -1 with an exception set if the initialization failed. */ @@ -3601,19 +3444,6 @@ } static PyObject * -imp_load_package(PyObject *self, PyObject *args) -{ - PyObject *name, *pathname; - PyObject * ret; - if (!PyArg_ParseTuple(args, "UO&:load_package", - &name, PyUnicode_FSDecoder, &pathname)) - return NULL; - ret = load_package(name, pathname); - Py_DECREF(pathname); - return ret; -} - -static PyObject * imp_reload(PyObject *self, PyObject *v) { return PyImport_ReloadModule(v); @@ -3764,7 +3594,6 @@ #ifdef HAVE_DYNAMIC_LOADING {"load_dynamic", imp_load_dynamic, METH_VARARGS}, #endif - {"load_package", imp_load_package, METH_VARARGS}, {"load_source", imp_load_source, METH_VARARGS}, {"_fix_co_filename", imp_fix_co_filename, METH_VARARGS}, {NULL, NULL} /* sentinel */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 04:29:00 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 16 Apr 2012 04:29:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/d72932e80130 changeset: 76343:d72932e80130 parent: 76342:4256df44023b parent: 76340:34f09c654a5b user: Brett Cannon date: Sun Apr 15 22:28:45 2012 -0400 summary: merge files: Lib/test/sha256.pem | 231 ++++++++++++++++--------------- Misc/NEWS | 3 + 2 files changed, 119 insertions(+), 115 deletions(-) diff --git a/Lib/test/sha256.pem b/Lib/test/sha256.pem --- a/Lib/test/sha256.pem +++ b/Lib/test/sha256.pem @@ -1,129 +1,128 @@ # Certificate chain for https://sha256.tbs-internet.com - 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=sha-256 production/CN=sha256.tbs-internet.com - i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC + 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=Certificats TBS X509/CN=ecom.tbs-x509.com + i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business -----BEGIN CERTIFICATE----- -MIIGXTCCBUWgAwIBAgIRAMmag+ygSAdxZsbyzYjhuW0wDQYJKoZIhvcNAQELBQAw -gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl +MIIGTjCCBTagAwIBAgIQOh3d9dNDPq1cSdJmEiMpqDANBgkqhkiG9w0BAQUFADCB +yTELMAkGA1UEBhMCRlIxETAPBgNVBAgTCENhbHZhZG9zMQ0wCwYDVQQHEwRDYWVu +MRUwEwYDVQQKEwxUQlMgSU5URVJORVQxSDBGBgNVBAsTP1Rlcm1zIGFuZCBDb25k +aXRpb25zOiBodHRwOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0EvcmVwb3NpdG9y +eTEYMBYGA1UECxMPVEJTIElOVEVSTkVUIENBMR0wGwYDVQQDExRUQlMgWDUwOSBD +QSBidXNpbmVzczAeFw0xMTAxMjUwMDAwMDBaFw0xMzAyMDUyMzU5NTlaMIHHMQsw +CQYDVQQGEwJGUjEOMAwGA1UEERMFMTQwMDAxETAPBgNVBAgTCENhbHZhZG9zMQ0w +CwYDVQQHEwRDQUVOMRswGQYDVQQJExIyMiBydWUgZGUgQnJldGFnbmUxFTATBgNV +BAoTDFRCUyBJTlRFUk5FVDEXMBUGA1UECxMOMDAwMiA0NDA0NDM4MTAxHTAbBgNV +BAsTFENlcnRpZmljYXRzIFRCUyBYNTA5MRowGAYDVQQDExFlY29tLnRicy14NTA5 +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRrlHUnJ++1lpcg +jtYco7cdmRe+EEfTmwPfCdfV3G1QfsTSvY6FfMpm/83pqHfT+4ANwr18wD9ZrAEN +G16mf9VdCGK12+TP7DmqeZyGIqlFFoahQnmb8EarvE43/1UeQ2CV9XmzwZvpqeli +LfXsFonawrY3H6ZnMwS64St61Z+9gdyuZ/RbsoZBbT5KUjDEG844QRU4OT1IGeEI +eY5NM5RNIh6ZNhVtqeeCxMS7afONkHQrOco73RdSTRck/Hj96Ofl3MHNHryr+AMK +DGFk1kLCZGpPdXtkxXvaDeQoiYDlil26CWc+YK6xyDPMdsWvoG14ZLyCpzMXA7/7 +4YAQRH0CAwEAAaOCAjAwggIsMB8GA1UdIwQYMBaAFBoJBMz5CY+7HqDO1KQUf0vV +I1jNMB0GA1UdDgQWBBQgOU8HsWzbmD4WZP5Wtdw7jca2WDAOBgNVHQ8BAf8EBAMC +BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +TAYDVR0gBEUwQzBBBgsrBgEEAYDlNwIBATAyMDAGCCsGAQUFBwIBFiRodHRwczov +L3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL0NQUzEwdwYDVR0fBHAwbjA3oDWgM4Yx +aHR0cDovL2NybC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNy +bDAzoDGgL4YtaHR0cDovL2NybC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5l +c3MuY3JsMIGwBggrBgEFBQcBAQSBozCBoDA9BggrBgEFBQcwAoYxaHR0cDovL2Ny +dC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNydDA5BggrBgEF +BQcwAoYtaHR0cDovL2NydC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5lc3Mu +Y3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wMwYDVR0R +BCwwKoIRZWNvbS50YnMteDUwOS5jb22CFXd3dy5lY29tLnRicy14NTA5LmNvbTAN +BgkqhkiG9w0BAQUFAAOCAQEArT4NHfbY87bGAw8lPV4DmHlmuDuVp/y7ltO3Ynse +3Rz8RxW2AzuO0Oy2F0Cu4yWKtMyEyMXyHqWtae7ElRbdTu5w5GwVBLJHClCzC8S9 +SpgMMQTx3Rgn8vjkHuU9VZQlulZyiPK7yunjc7c310S9FRZ7XxOwf8Nnx4WnB+No +WrfApzhhQl31w+RyrNxZe58hCfDDHmevRvwLjQ785ZoQXJDj2j3qAD4aI2yB8lB5 +oaE1jlCJzC7Kmz/Y9jzfmv/zAs1LQTm9ktevv4BTUFaGjv9jxnQ1xnS862ZiouLW +zZYIlYPf4F6JjXGiIQgQRglILUfq3ftJd9/ok9W9ZF8h8w== +-----END CERTIFICATE----- + 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business + i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root +-----BEGIN CERTIFICATE----- +MIIFPzCCBCegAwIBAgIQDlBz/++iRSmLDeVRHT/hADANBgkqhkiG9w0BAQUFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDcwOTE4MTkyMlow +gckxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -Q0EgU0dDMB4XDTEwMDIxODAwMDAwMFoXDTEyMDIxOTIzNTk1OVowgcsxCzAJBgNV -BAYTAkZSMQ4wDAYDVQQREwUxNDAwMDERMA8GA1UECBMIQ2FsdmFkb3MxDTALBgNV -BAcTBENBRU4xGzAZBgNVBAkTEjIyIHJ1ZSBkZSBCcmV0YWduZTEVMBMGA1UEChMM -VEJTIElOVEVSTkVUMRcwFQYDVQQLEw4wMDAyIDQ0MDQ0MzgxMDEbMBkGA1UECxMS -c2hhLTI1NiBwcm9kdWN0aW9uMSAwHgYDVQQDExdzaGEyNTYudGJzLWludGVybmV0 -LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbuM8VT7f0nntwu -N3F7v9KIBlhKNAxqCrziOXU5iqUt8HrQB3DtHbdmII+CpVUlwlmepsx6G+srEZ9a -MIGAy0nxi5aLb7watkyIdPjJTMvTUBQ/+RPWzt5JtYbbY9BlJ+yci0dctP74f4NU -ISLtlrEjUbf2gTohLrcE01TfmOF6PDEbB5PKDi38cB3NzKfizWfrOaJW6Q1C1qOJ -y4/4jkUREX1UFUIxzx7v62VfjXSGlcjGpBX1fvtABQOSLeE0a6gciDZs1REqroFf -5eXtqYphpTa14Z83ITXMfgg5Nze1VtMnzI9Qx4blYBw4dgQVEuIsYr7FDBOITDzc -VEVXZx0CAwEAAaOCAj8wggI7MB8GA1UdIwQYMBaAFAdEdoWTKLx/bXjSCuv6TEvf -2YIfMB0GA1UdDgQWBBSJKI/AYVI9RQNY0QPIqc8ej2QivTAOBgNVHQ8BAf8EBAMC -BaAwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIG -CisGAQQBgjcKAwMGCWCGSAGG+EIEATBMBgNVHSAERTBDMEEGCysGAQQBgOU3AgQB -MDIwMAYIKwYBBQUHAgEWJGh0dHBzOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0Ev -Q1BTNDBtBgNVHR8EZjBkMDKgMKAuhixodHRwOi8vY3JsLnRicy1pbnRlcm5ldC5j -b20vVEJTWDUwOUNBU0dDLmNybDAuoCygKoYoaHR0cDovL2NybC50YnMteDUwOS5j -b20vVEJTWDUwOUNBU0dDLmNybDCBpgYIKwYBBQUHAQEEgZkwgZYwOAYIKwYBBQUH -MAKGLGh0dHA6Ly9jcnQudGJzLWludGVybmV0LmNvbS9UQlNYNTA5Q0FTR0MuY3J0 -MDQGCCsGAQUFBzAChihodHRwOi8vY3J0LnRicy14NTA5LmNvbS9UQlNYNTA5Q0FT -R0MuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wPwYD -VR0RBDgwNoIXc2hhMjU2LnRicy1pbnRlcm5ldC5jb22CG3d3dy5zaGEyNTYudGJz -LWludGVybmV0LmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAA5NL0D4QSqhErhlkdPmz -XtiMvdGL+ZehM4coTRIpasM/Agt36Rc0NzCvnQwKE+wkngg1Gy2qe7Q0E/ziqBtB -fZYzdVgu1zdiL4kTaf+wFKYAFGsFbyeEmXysy+CMwaNoF2vpSjCU1UD56bEnTX/W -fxVZYxtBQUpnu2wOsm8cDZuZRv9XrYgAhGj9Tt6F0aVHSDGn59uwShG1+BVF/uju -SCyPTTjL1oc7YElJUzR/x4mQJYvtQI8gDIDAGEOs7v3R/gKa5EMfbUQUI4C84UbI -Yz09Jdnws/MkC/Hm1BZEqk89u7Hvfv+oHqEb0XaUo0TDfsxE0M1sMdnLb91QNQBm -UQ== ------END CERTIFICATE----- - 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC - i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root ------BEGIN CERTIFICATE----- -MIIFVjCCBD6gAwIBAgIQXpDZ0ETJMV02WTx3GTnhhTANBgkqhkiG9w0BAQUFADBv -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk -ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF -eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDYyNDE5MDYzMFow -gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl -bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u -ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -Q0EgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgOkO3f7wzN6 -rOjg45tR5vjBfzK7qmV9IBxb/QW9EEXxG+E7FNhZqQLtwGBKoSsHTnQqV75wWMk0 -9tinWvftBkSpj5sTi/8cbzJfUvTSVYh3Qxv6AVVjMMH/ruLjE6y+4PoaPs8WoYAQ -ts5R4Z1g8c/WnTepLst2x0/Wv7GmuoQi+gXvHU6YrBiu7XkeYhzc95QdviWSJRDk -owhb5K43qhcvjRmBfO/paGlCliDGZp8mHwrI21mwobWpVjTxZRwYO3bd4+TGcI4G -Ie5wmHwE8F7SK1tgSqbBacKjDa93j7txKkfz/Yd2n7TGqOXiHPsJpG655vrKtnXk -9vs1zoDeJQIDAQABo4IBljCCAZIwHQYDVR0OBBYEFAdEdoWTKLx/bXjSCuv6TEvf -2YIfMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMCAGA1UdJQQZ -MBcGCisGAQQBgjcKAwMGCWCGSAGG+EIEATAYBgNVHSAEETAPMA0GCysGAQQBgOU3 -AgQBMHsGA1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0Fk -ZFRydXN0RXh0ZXJuYWxDQVJvb3QuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9k -by5uZXQvQWRkVHJ1c3RFeHRlcm5hbENBUm9vdC5jcmwwgYAGCCsGAQUFBwEBBHQw -cjA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21vZG9jYS5jb20vQWRkVHJ1c3RV -VE5TR0NDQS5jcnQwNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvLm5ldC9B -ZGRUcnVzdFVUTlNHQ0NBLmNydDARBglghkgBhvhCAQEEBAMCAgQwDQYJKoZIhvcN -AQEFBQADggEBAK2zEzs+jcIrVK9oDkdDZNvhuBYTdCfpxfFs+OAujW0bIfJAy232 -euVsnJm6u/+OrqKudD2tad2BbejLLXhMZViaCmK7D9nrXHx4te5EP8rL19SUVqLY -1pTnv5dhNgEgvA7n5lIzDSYs7yRLsr7HJsYPr6SeYSuZizyX1SNz7ooJ32/F3X98 -RB0Mlc/E0OyOrkQ9/y5IrnpnaSora8CnUrV5XNOg+kyCz9edCyx4D5wXYcwZPVWz -8aDqquESrezPyjtfi4WRO4s/VD3HLZvOxzMrWAVYCDG9FxaOhF0QGuuG1F7F3GKV -v6prNyCl016kRl2j1UT+a7gLd8fA25A4C9E= +cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEdMBsGA1UEAxMUVEJTIFg1MDkg +Q0EgYnVzaW5lc3MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDB1PAU +qudCcz3tmyGcf+u6EkZqonKKHrV4gZYbvVkIRojmmlhfi/jwvpHvo8bqSt/9Rj5S +jhCDW0pcbI+IPPtD1Jy+CHNSfnMqVDy6CKQ3p5maTzCMG6ZT+XjnvcND5v+FtaiB +xk1iCX6uvt0jeUtdZvYbyytsSDE6c3Y5//wRxOF8tM1JxibwO3pyER26jbbN2gQz +m/EkdGjLdJ4svPk23WDAvQ6G0/z2LcAaJB+XLfqRwfQpHQvfKa1uTi8PivC8qtip +rmNQMMPMjxSK2azX8cKjjTDJiUKaCb4VHlJDWKEsCFRpgJAoAuX8f7Yfs1M4esGo +sWb3PGspK3O22uIlAgMBAAGjggF6MIIBdjAdBgNVHQ4EFgQUGgkEzPkJj7seoM7U +pBR/S9UjWM0wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwGAYD +VR0gBBEwDzANBgsrBgEEAYDlNwIBATB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8v +Y3JsLmNvbW9kb2NhLmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDA2oDSg +MoYwaHR0cDovL2NybC5jb21vZG8ubmV0L0FkZFRydXN0RXh0ZXJuYWxDQVJvb3Qu +Y3JsMIGGBggrBgEFBQcBAQR6MHgwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t +b2RvY2EuY29tL0FkZFRydXN0VVROU2VydmVyQ0EuY3J0MDkGCCsGAQUFBzAChi1o +dHRwOi8vY3J0LmNvbW9kby5uZXQvQWRkVHJ1c3RVVE5TZXJ2ZXJDQS5jcnQwEQYJ +YIZIAYb4QgEBBAQDAgIEMA0GCSqGSIb3DQEBBQUAA4IBAQA7mqrMgk/MrE6QnbNA +h4nRCn2ti4bg4w2C3lB6bSvRPnYwuNw9Jb8vuKkNFzRDxNJXqVDZdfFW5CVQJuyd +nfAx83+wk+spzvFaE1KhFYfN9G9pQfXUfvDRoIcJgPEKUXL1wRiOG+IjU3VVI8pg +IgqHkr7ylln5i5zCiFAPuIJmYUSFg/gxH5xkCNcjJqqrHrHatJr6Qrrke93joupw +oU1njfAcZtYp6fbiK6u2b1pJqwkVBE8RsfLnPhRj+SFbpvjv8Od7o/ieJhFIYQNU +k2jX2u8qZnAiNw93LZW9lpYjtuvMXq8QQppENNja5b53q7UwI+lU7ZGjZ7quuESp +J6/5 -----END CERTIFICATE----- 2 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root - i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC + i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -----BEGIN CERTIFICATE----- -MIIEZjCCA06gAwIBAgIQUSYKkxzif5zDpV954HKugjANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +MIIETzCCAzegAwIBAgIQHM5EYpUZep1jUvnyI6m2mDANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw0wNTA2MDcwODA5MTBaFw0xOTA2MjQxOTA2MzBaMG8xCzAJBgNVBAYT -AlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0 -ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB -IFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39xoz5vIABC05 -4E5b7R+8bA/Ntfojts7emxEzl6QpTH2Tn71KvJPtAxrjj8/lbVBa1pcplFqAsEl6 -2y6V/bjKvzc4LR4+kUGtcFbH8E8/6DKedMrIkFTpxl8PeJ2aQDwOrGGqXhSPnoeh -alDc15pOrwWzpnGUnHGzUGAKxxOdOAeGAqjpqGkmGJCrTLBPI6s6T4TY386f4Wlv -u9dC12tE5Met7m1BX3JacQg3s3llpFmglDf3AC8NwpJy2tA4ctsUqEXEXSp9t7TW -xO6szRNEt8kr3UMAJfphuWlqWCMRt6czj1Z1WfXNKddGtworZbbTQm8Vsrh7++/p -XVPVNFonAgMBAAGjgdgwgdUwHwYDVR0jBBgwFoAUUzLRs89/+uDxoF2FTpLSnkUd -tE8wHQYDVR0OBBYEFK29mHo0tCb3+sQmVO8DveAky1QaMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MBEGCWCGSAGG+EIBAQQEAwIBAjAgBgNVHSUEGTAX -BgorBgEEAYI3CgMDBglghkgBhvhCBAEwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDov -L2NybC51c2VydHJ1c3QuY29tL1VUTi1EQVRBQ29ycFNHQy5jcmwwDQYJKoZIhvcN -AQEFBQADggEBAMbuUxdoFLJRIh6QWA2U/b3xcOWGLcM2MY9USEbnLQg3vGwKYOEO -rVE04BKT6b64q7gmtOmWPSiPrmQH/uAB7MXjkesYoPF1ftsK5p+R26+udd8jkWjd -FwBaS/9kbHDrARrQkNnHptZt9hPk/7XJ0h4qy7ElQyZ42TCbTg0evmnv3+r+LbPM -+bDdtRTKkdSytaX7ARmjR3mfnYyVhzT4HziS2jamEfpr62vp3EV4FTkG101B5CHI -3C+H0be/SGB1pWLLJN47YaApIKa+xWycxOkKaSLvkTr6Jq/RW0GnOuL4OAdCq8Fb -+M5tug8EPzI0rNwEKNdwMBQmBsTkm5jVz3g= +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNMDUwNjA3MDgwOTEwWhcNMTkwNzA5MTgxOTIyWjBvMQswCQYD +VQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0 +IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5h +bCBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/caM+by +AAQtOeBOW+0fvGwPzbX6I7bO3psRM5ekKUx9k5+9SryT7QMa44/P5W1QWtaXKZRa +gLBJetsulf24yr83OC0ePpFBrXBWx/BPP+gynnTKyJBU6cZfD3idmkA8Dqxhql4U +j56HoWpQ3NeaTq8Fs6ZxlJxxs1BgCscTnTgHhgKo6ahpJhiQq0ywTyOrOk+E2N/O +n+Fpb7vXQtdrROTHre5tQV9yWnEIN7N5ZaRZoJQ39wAvDcKSctrQOHLbFKhFxF0q +fbe01sTurM0TRLfJK91DACX6YblpalgjEbenM49WdVn1zSnXRrcKK2W200JvFbK4 +e/vv6V1T1TRaJwIDAQABo4G9MIG6MB8GA1UdIwQYMBaAFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMB0GA1UdDgQWBBStvZh6NLQm9/rEJlTvA73gJMtUGjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAQIwRAYDVR0f +BD0wOzA5oDegNYYzaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly +c3QtSGFyZHdhcmUuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQByQhANOs4kClrwF8BW +onvUOGCSjRK52zYZgDXYNjDtmr5rJ6NyPFDNn+JxkLpjYetIFMTbSRe679Bt8m7a +gIAoQYFQtxMuyLnJegB2aEbQiIxh/tC21UcFF7ktdnDoTlA6w3pLuvunaI84Of3o +2YBrhzkTbCfaYk5JRlTpudW9DkUkHBsyx3nknPKnplkIGaK0jgn8E0n+SFabYaHk +I9LroYT/+JtLefh9lgBdAgVv0UPbzoGfuDsrk/Zh+UrgbLFpHoVnElhzbkh64Z0X +OGaJunQc68cCZu5HTn/aK7fBGMcVflRCXLVEQpU9PIAdGA8Ynvg684t8GMaKsRl1 +jIGZ -----END CERTIFICATE----- - 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC - i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC + 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware + i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -----BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -----END CERTIFICATE----- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -90,6 +90,9 @@ Tests ----- +- Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing + a test failure in test_ssl. + - Issue #14355: Regrtest now supports the standard unittest test loading, and will use it if a test file contains no `test_main` method. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Apr 16 05:33:45 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 16 Apr 2012 05:33:45 +0200 Subject: [Python-checkins] Daily reference leaks (2df37938b8e1): sum=924 Message-ID: results for 2df37938b8e1 on branch "default" -------------------------------------------- test_bz2 leaked [-1, -1, -1] references, sum=-3 test_concurrent_futures leaked [120, 120, 120] references, sum=360 test_gc leaked [3, 3, 3] references, sum=9 test_hashlib leaked [-1, -1, -1] references, sum=-3 test_import leaked [6, 6, 6] references, sum=18 test_lib2to3 leaked [14, 14, 14] references, sum=42 test_multiprocessing leaked [149, 149, 149] references, sum=447 test_runpy leaked [18, 18, 18] references, sum=54 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogoQ56hH', '-x'] From python-checkins at python.org Mon Apr 16 07:10:31 2012 From: python-checkins at python.org (brian.curtin) Date: Mon, 16 Apr 2012 07:10:31 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_=2310854=2E_Make_use_of?= =?utf8?q?_the_new_path_and_name_attributes_on_ImportError?= Message-ID: http://hg.python.org/cpython/rev/f341b99bb370 changeset: 76344:f341b99bb370 user: Brian Curtin date: Mon Apr 16 00:10:17 2012 -0500 summary: Fix #10854. Make use of the new path and name attributes on ImportError for extension modules on Windows. files: Lib/test/test_import.py | 18 ++++++++++++++++++ Misc/NEWS | 4 ++++ Python/dynload_win.c | 5 +++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -337,6 +337,24 @@ del sys.path[0] remove_files(TESTFN) + @unittest.skipUnless(sys.platform == "win32", "Windows specific") + def test_extension_import_fail(self): + # Issue 1559549 added `name` and `path` attributes to ImportError + # in order to provide better detail. Issue 10854 implemented those + # attributes on import failures of extensions on Windows. + debug = True if sys.executable[-6:] == "_d.exe" else False + pkg_name = "extension" + pkg_file = pkg_name + "{}".format("_d.pyd" if debug else ".pyd") + with open(pkg_file, "w"): pass + try: + with self.assertRaises(ImportError) as err: + import extension + self.assertEqual(err.exception.name, pkg_name) + # The path we get back has the dot-slash, e.g., ".\\extension.pyd" + self.assertEqual(os.path.relpath(err.exception.path), pkg_file) + finally: + unlink(pkg_file) + class PycRewritingTests(unittest.TestCase): # Test that the `co_filename` attribute on code objects always points diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #10854: The ImportError raised when an extension module on Windows + fails to import now uses the new path and name attributes from + Issue #1559549. + - Issue #14582: Import directly returns the module as returned by a loader when possible instead of fetching it from sys.modules. diff --git a/Python/dynload_win.c b/Python/dynload_win.c --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -254,8 +254,9 @@ theLength)); } if (message != NULL) { - PyErr_SetObject(PyExc_ImportError, message); - Py_DECREF(message); + PyErr_SetFromImportErrorWithNameAndPath(message, + PyUnicode_FromString(shortname), + pathname); } return NULL; } else { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 12:36:35 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 16 Apr 2012 12:36:35 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_link_to_the_=22?= =?utf8?q?gettimeofday=28=29_should_never_be_used_to_measure_time=22?= Message-ID: http://hg.python.org/peps/rev/e68639195a51 changeset: 4254:e68639195a51 user: Victor Stinner date: Mon Apr 16 12:33:05 2012 +0200 summary: PEP 418: Add link to the "gettimeofday() should never be used to measure time" article Mention also authors of other links. files: pep-0418.txt | 26 ++++++++++++++------------ 1 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1472,7 +1472,7 @@ * `Monoclock.nano_count() `_ uses clock_gettime(CLOCK_MONOTONIC) and returns a number of nanoseconds -* `monotonic_clock `_ +* `monotonic_clock `_ by Thomas Habets * `Perl: Time::HiRes `_ exposes clock_gettime(CLOCK_MONOTONIC) * `Ruby: AbsoluteTime.now @@ -1504,17 +1504,19 @@ Time: +* `gettimeofday() should never be used to measure time + `_ by Thomas Habets (2010-09-05) * `hrtimers - subsystem for high-resolution kernel timers `_ * `C++ Timeout Specification - `_ + `_ by Lawrence Crowl (2010-08-19) * `Windows: Game Timing and Multicore Processors - `_ + `_ by Chuck Walbourn (December 2005) * `Implement a Continuously Updating, High-Resolution Time Provider for Windows - `_ + `_ by Johan Nilsson (March 2004) * `clockspeed `_ uses a hardware tick - counter to compensate for a persistently fast or slow system time + counter to compensate for a persistently fast or slow system time, by D. J. Bernstein (1998) * `Retrieving system time `_ lists hardware clocks and time functions with their resolution and @@ -1527,9 +1529,9 @@ * `When microseconds matter `_: How the IBM High Resolution Time Stamp Facility accurately measures itty - bits of time + bits of time, by W. Nathaniel Mills, III (Apr 2002) * `Win32 Performance Measurement Options - `_ by Matthew Wilson, May 01, 2003 + `_ by Matthew Wilson (May, 2003) * `Counter Availability and Characteristics for Feed-forward Based Synchronization `_ by Timothy Broomhead, Julien Ridoux, Darryl Veitch (2009) @@ -1537,15 +1539,15 @@ * `System Management Interrupt Free Hardware `_ - (Keith Mannthey, 2009) + by Keith Mannthey (2009) * `IBM Real-Time "SMI Free" mode driver - `_ + `_ by Keith Mannthey (Feb 2009) * `Fixing Realtime problems caused by SMI on Ubuntu `_ * `[RFC] simple SMI detector - `_ - * `[PATCH 2.6.34-rc3] A nonintrusive SMI sniffer for x86. - `_ + `_ by Jon Masters (Jan 2009) + * `[PATCH 2.6.34-rc3] A nonintrusive SMI sniffer for x86 + `_ by Joe Korty (2010-04) Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 16 13:53:46 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 16 Apr 2012 13:53:46 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_two_alternative?= =?utf8?q?_names_for_time=2Eperf=5Fcounter=28=29?= Message-ID: http://hg.python.org/peps/rev/72c880abb93f changeset: 4255:72c880abb93f user: Victor Stinner date: Mon Apr 16 13:53:24 2012 +0200 summary: PEP 418: Add two alternative names for time.perf_counter() files: pep-0418.txt | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -416,8 +416,10 @@ Other names for time.perf_counter() ----------------------------------- +* time.high_precision() +* time.highres() * time.hires() -* time.highres() +* time.performance_counter() * time.timer() Only expose operating system clocks -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 16 13:58:50 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 16 Apr 2012 13:58:50 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_time=2Eperf=5Fcount?= =?utf8?q?er=28=29_is_always_available?= Message-ID: http://hg.python.org/peps/rev/9274bcf0feca changeset: 4256:9274bcf0feca user: Victor Stinner date: Mon Apr 16 13:58:24 2012 +0200 summary: PEP 418: time.perf_counter() is always available files: pep-0418.txt | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -179,6 +179,8 @@ so that only the difference between the results of consecutive calls is valid and is a number of seconds. +It is available on all platforms. + Pseudo-code:: def perf_counter(): -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 16 15:44:44 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 15:44:44 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NDUy?= =?utf8?q?=3A_remove_BOM_insertion_code=2E?= Message-ID: http://hg.python.org/cpython/rev/af46a001d5ec changeset: 76345:af46a001d5ec branch: 2.7 parent: 76341:33bc53e0aa9e user: Vinay Sajip date: Mon Apr 16 14:38:23 2012 +0100 summary: Issue #14452: remove BOM insertion code. files: Lib/logging/handlers.py | 2 -- Misc/NEWS | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -821,8 +821,6 @@ # Message is a string. Convert to bytes as required by RFC 5424 if type(msg) is unicode: msg = msg.encode('utf-8') - if codecs: - msg = codecs.BOM_UTF8 + msg msg = prio + msg try: if self.unixsocket: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,8 @@ Library ------- +- Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. + - Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied to a collection of size > sys.maxsize / 2. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 15:44:45 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 15:44:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Closes_=2314452?= =?utf8?q?=3A_remove_BOM_insertion_code=2E?= Message-ID: http://hg.python.org/cpython/rev/89ab589f6fa7 changeset: 76346:89ab589f6fa7 branch: 3.2 parent: 76339:f323b37ef6c1 user: Vinay Sajip date: Mon Apr 16 14:39:53 2012 +0100 summary: Closes #14452: remove BOM insertion code. files: Lib/logging/handlers.py | 2 -- Misc/NEWS | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -808,8 +808,6 @@ prio = prio.encode('utf-8') # Message is a string. Convert to bytes as required by RFC 5424 msg = msg.encode('utf-8') - if codecs: - msg = codecs.BOM_UTF8 + msg msg = prio + msg try: if self.unixsocket: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -43,6 +43,8 @@ Library ------- +- Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. + - Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied to a collection of size > sys.maxsize / 2. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 15:44:48 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 15:44:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Closes_=2314452=3A_remove_BOM_insertion_code=2E?= Message-ID: http://hg.python.org/cpython/rev/372aa4267a43 changeset: 76347:372aa4267a43 parent: 76344:f341b99bb370 parent: 76346:89ab589f6fa7 user: Vinay Sajip date: Mon Apr 16 14:44:31 2012 +0100 summary: Closes #14452: remove BOM insertion code. files: Lib/logging/handlers.py | 2 +- Misc/NEWS | 2 ++ 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -850,7 +850,7 @@ prio = prio.encode('utf-8') # Message is a string. Convert to bytes as required by RFC 5424 msg = msg.encode('utf-8') - msg = prio + BOM_UTF8 + msg + msg = prio + msg try: if self.unixsocket: try: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -36,6 +36,8 @@ Library ------- +- Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. + - Issue #14386: Expose the dict_proxy internal type as types.MappingProxyType. - Issue #13959: Make imp.reload() always use a module's __loader__ to perform -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 16:29:39 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 16:29:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Added_cookbook_?= =?utf8?q?example_for_log_insertion=2E?= Message-ID: http://hg.python.org/cpython/rev/fe0a968c7266 changeset: 76348:fe0a968c7266 branch: 2.7 parent: 76345:af46a001d5ec user: Vinay Sajip date: Mon Apr 16 15:27:55 2012 +0100 summary: Added cookbook example for log insertion. files: Doc/howto/logging-cookbook.rst | 44 ++++++++++++++++++++++ 1 files changed, 44 insertions(+), 0 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -745,3 +745,47 @@ For more information about this configuration, you can see the `relevant section `_ of the Django documentation. + +Inserting a BOM into messages sent to a SysLogHandler +----------------------------------------------------- + +`RFC 5424 `_ requires that a +Unicode message be sent to a syslog daemon as a set of bytes which have the +following structure: an optional pure-ASCII component, followed by a UTF-8 Byte +Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant +section of the specification `_.) + +In Python 2.6 and 2.7, code was added to +:class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but +unfortunately, it was implemented incorrectly, with the BOM appearing at the +beginning of the message and hence not allowing any pure-ASCII component to +appear before it. + +As this behaviour is broken, the incorrect BOM insertion code is being removed +from Python 2.7.4 and later. However, it is not being replaced, and if you +want to produce RFC 5424-compliant messages which includes a BOM, an optional +pure-ASCII sequence before it and arbitrary Unicode after it, encoded using +UTF-8, then you need to do the following: + +#. Attach a :class:`~logging.Formatter` instance to your + :class:`~logging.handlers.SysLogHandler` instance, with a format string + such as:: + + u"ASCII section\ufeffUnicode section" + + The Unicode code point ``u'\feff```, when encoded using UTF-8, will be + encoded as a UTF-8 BOM -- the bytestring ``'\xef\xbb\bf'``. + +#. Replace the ASCII section with whatever placeholders you like, but make sure + that the data that appears in there after substitution is always ASCII (that + way, it will remain unchanged after UTF-8 encoding). + +#. Replace the Unicode section with whatever placeholders you like; if the data + which appears there after substitution is Unicode, that's fine -- it will be + encoded using UTF-8. + +If the formatted message is Unicode, it *will* be encoded using UTF-8 encoding +by ``SysLogHandler``. If you follow these rules, you should be able to produce +RFC 5424-compliant messages. If you don't, logging may not complain, but your +messages will not be RFC 5424-compliant, and your syslog daemon may complain. + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 16:29:40 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 16:29:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Added_cookbook_?= =?utf8?q?example_for_BOM_insertion=2E?= Message-ID: http://hg.python.org/cpython/rev/8a52fe162ecf changeset: 76349:8a52fe162ecf branch: 3.2 parent: 76346:89ab589f6fa7 user: Vinay Sajip date: Mon Apr 16 15:28:50 2012 +0100 summary: Added cookbook example for BOM insertion. files: Doc/howto/logging-cookbook.rst | 44 ++++++++++++++++++++++ 1 files changed, 44 insertions(+), 0 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1544,3 +1544,47 @@ if __name__ == '__main__': main() + +Inserting a BOM into messages sent to a SysLogHandler +----------------------------------------------------- + +`RFC 5424 `_ requires that a +Unicode message be sent to a syslog daemon as a set of bytes which have the +following structure: an optional pure-ASCII component, followed by a UTF-8 Byte +Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant +section of the specification `_.) + +In Python 2.6 and 2.7, code was added to +:class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but +unfortunately, it was implemented incorrectly, with the BOM appearing at the +beginning of the message and hence not allowing any pure-ASCII component to +appear before it. + +As this behaviour is broken, the incorrect BOM insertion code is being removed +from Python 2.7.4 and later. However, it is not being replaced, and if you +want to produce RFC 5424-compliant messages which includes a BOM, an optional +pure-ASCII sequence before it and arbitrary Unicode after it, encoded using +UTF-8, then you need to do the following: + +#. Attach a :class:`~logging.Formatter` instance to your + :class:`~logging.handlers.SysLogHandler` instance, with a format string + such as:: + + u"ASCII section\ufeffUnicode section" + + The Unicode code point ``u'\feff```, when encoded using UTF-8, will be + encoded as a UTF-8 BOM -- the bytestring ``'\xef\xbb\bf'``. + +#. Replace the ASCII section with whatever placeholders you like, but make sure + that the data that appears in there after substitution is always ASCII (that + way, it will remain unchanged after UTF-8 encoding). + +#. Replace the Unicode section with whatever placeholders you like; if the data + which appears there after substitution is Unicode, that's fine -- it will be + encoded using UTF-8. + +If the formatted message is Unicode, it *will* be encoded using UTF-8 encoding +by ``SysLogHandler``. If you follow these rules, you should be able to produce +RFC 5424-compliant messages. If you don't, logging may not complain, but your +messages will not be RFC 5424-compliant, and your syslog daemon may complain. + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 16:29:41 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 16:29:41 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merged_cookbook_update_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/7f87afa2864f changeset: 76350:7f87afa2864f parent: 76347:372aa4267a43 parent: 76349:8a52fe162ecf user: Vinay Sajip date: Mon Apr 16 15:29:28 2012 +0100 summary: Merged cookbook update from 3.2. files: Doc/howto/logging-cookbook.rst | 44 ++++++++++++++++++++++ 1 files changed, 44 insertions(+), 0 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1571,3 +1571,47 @@ if __name__ == '__main__': main() + +Inserting a BOM into messages sent to a SysLogHandler +----------------------------------------------------- + +`RFC 5424 `_ requires that a +Unicode message be sent to a syslog daemon as a set of bytes which have the +following structure: an optional pure-ASCII component, followed by a UTF-8 Byte +Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant +section of the specification `_.) + +In Python 2.6 and 2.7, code was added to +:class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but +unfortunately, it was implemented incorrectly, with the BOM appearing at the +beginning of the message and hence not allowing any pure-ASCII component to +appear before it. + +As this behaviour is broken, the incorrect BOM insertion code is being removed +from Python 2.7.4 and later. However, it is not being replaced, and if you +want to produce RFC 5424-compliant messages which includes a BOM, an optional +pure-ASCII sequence before it and arbitrary Unicode after it, encoded using +UTF-8, then you need to do the following: + +#. Attach a :class:`~logging.Formatter` instance to your + :class:`~logging.handlers.SysLogHandler` instance, with a format string + such as:: + + u"ASCII section\ufeffUnicode section" + + The Unicode code point ``u'\feff```, when encoded using UTF-8, will be + encoded as a UTF-8 BOM -- the bytestring ``'\xef\xbb\bf'``. + +#. Replace the ASCII section with whatever placeholders you like, but make sure + that the data that appears in there after substitution is always ASCII (that + way, it will remain unchanged after UTF-8 encoding). + +#. Replace the Unicode section with whatever placeholders you like; if the data + which appears there after substitution is Unicode, that's fine -- it will be + encoded using UTF-8. + +If the formatted message is Unicode, it *will* be encoded using UTF-8 encoding +by ``SysLogHandler``. If you follow these rules, you should be able to produce +RFC 5424-compliant messages. If you don't, logging may not complain, but your +messages will not be RFC 5424-compliant, and your syslog daemon may complain. + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 16:51:01 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 16:51:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Tweaked_format_?= =?utf8?q?of_cookbook_example=2E?= Message-ID: http://hg.python.org/cpython/rev/de27fedaeb25 changeset: 76351:de27fedaeb25 branch: 2.7 parent: 76348:fe0a968c7266 user: Vinay Sajip date: Mon Apr 16 15:45:11 2012 +0100 summary: Tweaked format of cookbook example. files: Doc/howto/logging-cookbook.rst | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -771,10 +771,10 @@ :class:`~logging.handlers.SysLogHandler` instance, with a format string such as:: - u"ASCII section\ufeffUnicode section" + u'ASCII section\ufeffUnicode section' The Unicode code point ``u'\feff```, when encoded using UTF-8, will be - encoded as a UTF-8 BOM -- the bytestring ``'\xef\xbb\bf'``. + encoded as a UTF-8 BOM -- the byte-string ``'\xef\xbb\xbf'``. #. Replace the ASCII section with whatever placeholders you like, but make sure that the data that appears in there after substitution is always ASCII (that @@ -785,7 +785,8 @@ encoded using UTF-8. If the formatted message is Unicode, it *will* be encoded using UTF-8 encoding -by ``SysLogHandler``. If you follow these rules, you should be able to produce -RFC 5424-compliant messages. If you don't, logging may not complain, but your -messages will not be RFC 5424-compliant, and your syslog daemon may complain. +by ``SysLogHandler``. If you follow the above rules, you should be able to +produce RFC 5424-compliant messages. If you don't, logging may not complain, +but your messages will not be RFC 5424-compliant, and your syslog daemon may +complain. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 16:51:02 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 16:51:02 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Tweaked_format_?= =?utf8?q?of_cookbook_example=2E?= Message-ID: http://hg.python.org/cpython/rev/481794505ac2 changeset: 76352:481794505ac2 branch: 3.2 parent: 76349:8a52fe162ecf user: Vinay Sajip date: Mon Apr 16 15:46:18 2012 +0100 summary: Tweaked format of cookbook example. files: Doc/howto/logging-cookbook.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1570,10 +1570,10 @@ :class:`~logging.handlers.SysLogHandler` instance, with a format string such as:: - u"ASCII section\ufeffUnicode section" + 'ASCII section\ufeffUnicode section' - The Unicode code point ``u'\feff```, when encoded using UTF-8, will be - encoded as a UTF-8 BOM -- the bytestring ``'\xef\xbb\bf'``. + The Unicode code point ``'\feff```, when encoded using UTF-8, will be + encoded as a UTF-8 BOM -- the byte-string ``b'\xef\xbb\xbf'``. #. Replace the ASCII section with whatever placeholders you like, but make sure that the data that appears in there after substitution is always ASCII (that @@ -1583,8 +1583,8 @@ which appears there after substitution is Unicode, that's fine -- it will be encoded using UTF-8. -If the formatted message is Unicode, it *will* be encoded using UTF-8 encoding -by ``SysLogHandler``. If you follow these rules, you should be able to produce +The formatted message *will* be encoded using UTF-8 encoding by +``SysLogHandler``. If you follow the above rules, you should be able to produce RFC 5424-compliant messages. If you don't, logging may not complain, but your messages will not be RFC 5424-compliant, and your syslog daemon may complain. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 16:51:03 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 16:51:03 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merged_tweaks_to_cookbook_example_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/386116ce00f7 changeset: 76353:386116ce00f7 parent: 76350:7f87afa2864f parent: 76352:481794505ac2 user: Vinay Sajip date: Mon Apr 16 15:47:05 2012 +0100 summary: Merged tweaks to cookbook example from 3.2. files: Doc/howto/logging-cookbook.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1597,10 +1597,10 @@ :class:`~logging.handlers.SysLogHandler` instance, with a format string such as:: - u"ASCII section\ufeffUnicode section" + 'ASCII section\ufeffUnicode section' - The Unicode code point ``u'\feff```, when encoded using UTF-8, will be - encoded as a UTF-8 BOM -- the bytestring ``'\xef\xbb\bf'``. + The Unicode code point ``'\feff```, when encoded using UTF-8, will be + encoded as a UTF-8 BOM -- the byte-string ``b'\xef\xbb\xbf'``. #. Replace the ASCII section with whatever placeholders you like, but make sure that the data that appears in there after substitution is always ASCII (that @@ -1610,8 +1610,8 @@ which appears there after substitution is Unicode, that's fine -- it will be encoded using UTF-8. -If the formatted message is Unicode, it *will* be encoded using UTF-8 encoding -by ``SysLogHandler``. If you follow these rules, you should be able to produce +The formatted message *will* be encoded using UTF-8 encoding by +``SysLogHandler``. If you follow the above rules, you should be able to produce RFC 5424-compliant messages. If you don't, logging may not complain, but your messages will not be RFC 5424-compliant, and your syslog daemon may complain. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 17:22:46 2012 From: python-checkins at python.org (vinay.sajip) Date: Mon, 16 Apr 2012 17:22:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Closes_=2314452=3A_brought_?= =?utf8?q?tests_in_line_with_removal_of_BOM_insertion_code=2E?= Message-ID: http://hg.python.org/cpython/rev/603301cfb194 changeset: 76354:603301cfb194 user: Vinay Sajip date: Mon Apr 16 16:22:38 2012 +0100 summary: Closes #14452: brought tests in line with removal of BOM insertion code. files: Lib/test/test_logging.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1480,17 +1480,17 @@ logger = logging.getLogger("slh") logger.error("sp\xe4m") self.handled.wait() - self.assertEqual(self.log_output, b'<11>\xef\xbb\xbfsp\xc3\xa4m\x00') + self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00') self.handled.clear() self.sl_hdlr.append_nul = False logger.error("sp\xe4m") self.handled.wait() - self.assertEqual(self.log_output, b'<11>\xef\xbb\xbfsp\xc3\xa4m') + self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m') self.handled.clear() self.sl_hdlr.ident = "h\xe4m-" logger.error("sp\xe4m") self.handled.wait() - self.assertEqual(self.log_output, b'<11>\xef\xbb\xbfh\xc3\xa4m-sp\xc3\xa4m') + self.assertEqual(self.log_output, b'<11>h\xc3\xa4m-sp\xc3\xa4m') @unittest.skipUnless(threading, 'Threading required for this test.') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 17:36:09 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 16 Apr 2012 17:36:09 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Add_an_explicit_mention_of_?= =?utf8?q?a_backwards-incompatible_fix_that_importlib?= Message-ID: http://hg.python.org/cpython/rev/6d767a08a1ba changeset: 76355:6d767a08a1ba user: Brett Cannon date: Mon Apr 16 11:35:55 2012 -0400 summary: Add an explicit mention of a backwards-incompatible fix that importlib implicitly fixed. 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 @@ -21,6 +21,9 @@ any of the dtoa.c string <-> float conversion functions, on MSVC builds of Python. This fixes issues when embedding Python in a Delphi app. +- __import__() now matches PEP 328 and documentation by defaulting 'index' to 0 + instead of -1 and removing support for negative values. + - Issue #2377: Make importlib the implementation of __import__(). - Issue #1559549: ImportError now has 'name' and 'path' attributes that are set -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 17:58:29 2012 From: python-checkins at python.org (local-hg) Date: Mon, 16 Apr 2012 17:58:29 +0200 Subject: [Python-checkins] =?utf8?q?hooks=3A_Remove_binary_diffs_from_comm?= =?utf8?q?it_e-mails?= Message-ID: http://hg.python.org/hooks/rev/c3442040f1d0 changeset: 79:c3442040f1d0 user: hg repo admin date: Mon Apr 16 17:58:29 2012 +0200 summary: Remove binary diffs from commit e-mails files: mail.py | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/mail.py b/mail.py --- a/mail.py +++ b/mail.py @@ -30,6 +30,20 @@ smtp.sendmail(sender, to, msg.as_string()) smtp.close() +def strip_bin_diffs(chunks): + stripped = [] + for chunk in chunks: + lines = chunk.splitlines(True) + try: + i = lines.index('GIT binary patch\n') + except ValueError: + pass + else: + lines = lines[:i+1] + ['[stripped]\n'] + chunk = ''.join(lines) + stripped.append(chunk) + return stripped + def _incoming(ui, repo, **kwargs): # Ensure that no fancying of output is enabled (e.g. coloring) os.environ['TERM'] = 'dumb' @@ -67,6 +81,7 @@ for line in iterlines([''.join(diffstat)]): body.append(' ' + line) body += ['', ''] + diffchunks = strip_bin_diffs(diffchunks) body.append(''.join(chunk for chunk in diffchunks)) body.append('-- ') -- Repository URL: http://hg.python.org/hooks From python-checkins at python.org Mon Apr 16 18:02:30 2012 From: python-checkins at python.org (local-hg) Date: Mon, 16 Apr 2012 18:02:30 +0200 Subject: [Python-checkins] =?utf8?q?hooks=3A_Strengthen_a_bit?= Message-ID: http://hg.python.org/hooks/rev/7bfbd6ebe503 changeset: 80:7bfbd6ebe503 user: hg repo admin date: Mon Apr 16 18:02:30 2012 +0200 summary: Strengthen a bit files: mail.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/mail.py b/mail.py --- a/mail.py +++ b/mail.py @@ -35,7 +35,8 @@ for chunk in chunks: lines = chunk.splitlines(True) try: - i = lines.index('GIT binary patch\n') + # This is the second or third line usually + i = lines.index('GIT binary patch\n', 0, 4) except ValueError: pass else: -- Repository URL: http://hg.python.org/hooks From python-checkins at python.org Mon Apr 16 18:32:06 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 18:32:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Avoid_rebuilding_all_C_file?= =?utf8?q?s_when_importlib=2Eh_is_updated=2E?= Message-ID: http://hg.python.org/cpython/rev/2a532a322a9c changeset: 76356:2a532a322a9c user: Antoine Pitrou date: Mon Apr 16 18:29:28 2012 +0200 summary: Avoid rebuilding all C files when importlib.h is updated. files: Makefile.pre.in | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -702,6 +702,8 @@ Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \ $(BYTESTR_DEPS) +Python/frozen.o: $(srcdir)/Python/importlib.h + Objects/typeobject.o: $(srcdir)/Objects/typeslots.inc $(srcdir)/Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py $(PYTHON) $(srcdir)/Objects/typeslots.py < $(srcdir)/Include/typeslots.h > $(srcdir)/Objects/typeslots.inc @@ -792,7 +794,6 @@ $(srcdir)/Include/unicodeobject.h \ $(srcdir)/Include/warnings.h \ $(srcdir)/Include/weakrefobject.h \ - $(srcdir)/Python/importlib.h \ pyconfig.h \ $(PARSER_HEADERS) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 18:32:07 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 18:32:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Avoid_compiler_warning_due_?= =?utf8?q?to_stray_=5Cx00?= Message-ID: http://hg.python.org/cpython/rev/e97ead910cc1 changeset: 76357:e97ead910cc1 user: Antoine Pitrou date: Mon Apr 16 18:30:54 2012 +0200 summary: Avoid compiler warning due to stray \x00 files: Python/freeze_importlib.py | 4 ++-- Python/importlib.h | Bin 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/freeze_importlib.py b/Python/freeze_importlib.py --- a/Python/freeze_importlib.py +++ b/Python/freeze_importlib.py @@ -22,9 +22,9 @@ line.append('%d,' % c) lines.append(''.join(line)) lines.append('};\n') - with open(output_path, 'w') as output_file: + with open(output_path, 'w', encoding='utf-8') as output_file: output_file.write('\n'.join(lines)) - output_file.write('\u0000') + output_file.write('/* Mercurial binary marker: \x00 */') if __name__ == '__main__': diff --git a/Python/importlib.h b/Python/importlib.h index f11dcbb131c5f7b77075b5d4c0523e52f33a1c6b..3a03c462530658669296e8e99237c26924ff24b7 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 18:49:49 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 18:49:49 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_reference_loss_on_Py=5F?= =?utf8?q?None_when_None_is_encountered_in_sys=2Emodules=2E?= Message-ID: http://hg.python.org/cpython/rev/feeb1ca9e93c changeset: 76358:feeb1ca9e93c user: Antoine Pitrou date: Mon Apr 16 18:48:49 2012 +0200 summary: Fix reference loss on Py_None when None is encountered in sys.modules. files: Python/import.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2827,6 +2827,7 @@ if (msg != NULL) { PyErr_SetFromImportErrorWithName(msg, abs_name); } + mod = NULL; goto error_with_unlock; } else if (mod != NULL) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 21:30:59 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 21:30:59 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_refleak_in_test=5Fgc?= Message-ID: http://hg.python.org/cpython/rev/f4977fcbe57f changeset: 76359:f4977fcbe57f user: Antoine Pitrou date: Mon Apr 16 21:29:02 2012 +0200 summary: Fix refleak in test_gc files: Lib/test/test_gc.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -551,6 +551,7 @@ gc.set_debug(0) gc.callbacks.append(self.cb1) gc.callbacks.append(self.cb2) + self.othergarbage = [] def tearDown(self): # Restore gc state @@ -566,9 +567,9 @@ if isinstance(obj, Uncollectable): obj.partner = None del gc.garbage[:] + del self.othergarbage gc.collect() - othergarbage = [] def preclean(self): # Remove all fluff from the system. Invoke this function # manually rather than through self.setUp() for maximum -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 21:30:59 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 21:30:59 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_pep8-ize_test_names?= Message-ID: http://hg.python.org/cpython/rev/b44eb630bf0a changeset: 76360:b44eb630bf0a user: Antoine Pitrou date: Mon Apr 16 21:29:58 2012 +0200 summary: pep8-ize test names files: Lib/test/test_gc.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -593,7 +593,7 @@ for e in uc: e.partner = None - def testCollect(self): + def test_collect(self): self.preclean() gc.collect() # Algorithmically verify the contents of self.visit @@ -620,14 +620,14 @@ self.assertTrue("collected" in info) self.assertTrue("uncollectable" in info) - def testCollectGen(self): + def test_collect_generation(self): self.preclean() gc.collect(2) for v in self.visit: info = v[2] self.assertEqual(info["generation"], 2) - def testCollectGarbage(self): + def test_collect_garbage(self): self.preclean() # Each of these cause four objects to be garbage: Two # Uncolectables and their instance dicts. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 21:54:47 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 21:54:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_a_refleak?= Message-ID: http://hg.python.org/cpython/rev/a3e9d5c239c4 changeset: 76361:a3e9d5c239c4 user: Antoine Pitrou date: Mon Apr 16 21:52:45 2012 +0200 summary: Fix a refleak files: Python/import.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2782,10 +2782,11 @@ } base = PyUnicode_Substring(package, 0, last_dot); if (PyUnicode_GET_LENGTH(name) > 0) { - PyObject *borrowed_dot = NULL; - PyObject *seq = PyTuple_Pack(2, base, name); + PyObject *borrowed_dot, *seq = NULL; borrowed_dot = _PyUnicode_FromId(&single_dot); + seq = PyTuple_Pack(2, base, name); + Py_DECREF(base); if (borrowed_dot == NULL || seq == NULL) { goto error; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 22:07:37 2012 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 16 Apr 2012 22:07:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_another_refleak?= Message-ID: http://hg.python.org/cpython/rev/9d8839289e18 changeset: 76362:9d8839289e18 user: Antoine Pitrou date: Mon Apr 16 22:06:21 2012 +0200 summary: Fix another refleak files: Python/import.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2881,11 +2881,15 @@ Py_INCREF(final_mod); } else { - Py_ssize_t cut_off = PyUnicode_GetLength(name) - - PyUnicode_GetLength(front); - Py_ssize_t abs_name_len = PyUnicode_GetLength(abs_name); + Py_ssize_t cut_off = PyUnicode_GET_LENGTH(name) - + PyUnicode_GET_LENGTH(front); + Py_ssize_t abs_name_len = PyUnicode_GET_LENGTH(abs_name); PyObject *to_return = PyUnicode_Substring(abs_name, 0, abs_name_len - cut_off); + Py_DECREF(front); + if (to_return == NULL) { + goto error_with_unlock; + } final_mod = PyDict_GetItem(interp->modules, to_return); Py_DECREF(to_return); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 22:14:45 2012 From: python-checkins at python.org (brian.curtin) Date: Mon, 16 Apr 2012 22:14:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Add_documentation_for_the_n?= =?utf8?q?ew_PyErr=5FSetFromImport*_functions?= Message-ID: http://hg.python.org/cpython/rev/5cc8b717b38c changeset: 76363:5cc8b717b38c user: Brian Curtin date: Mon Apr 16 15:14:36 2012 -0500 summary: Add documentation for the new PyErr_SetFromImport* functions files: Doc/c-api/exceptions.rst | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -229,6 +229,24 @@ Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, with an additional parameter specifying the exception type to be raised. Availability: Windows. +.. c:function:: PyObject* PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs) + + This is a convenience function to set an *exc* with the given *args* and + *kwargs* values. If *args* is ``NULL``, an empty :func:`tuple` will be + created when *exc* is created via :c:func:`PyObject_Call`. + +.. c:function:: PyObject* PyErr_SetFromImportErrorWithName(PyObject *msg, PyObject *name) + + This is a convenience function to raise :exc:`ImportError`. *msg* will be + set as the exception's message string, and *name* will be set as the + :exc:`ImportError`'s ``name`` attribute. + +.. c:function:: PyObject* PyErr_SetFromImportErrorWithNameAndPath(PyObject *msg, PyObject *name, PyObject *path) + + This is a convenience function to raise :exc:`ImportError`. *msg* will be + set as the exception's message string. Both *name* and *path* will be set + as the :exc:`ImportError`'s respective ``name`` and ``path`` attributes. + .. c:function:: void PyErr_SyntaxLocationEx(char *filename, int lineno, int col_offset) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 16 22:24:11 2012 From: python-checkins at python.org (brian.curtin) Date: Mon, 16 Apr 2012 22:24:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Correct_warnings_when_build?= =?utf8?q?ing_the_docs_for_the_nonexistet_=3Aarg=3A_role=2E_Changed?= Message-ID: http://hg.python.org/cpython/rev/a1b38ade5def changeset: 76364:a1b38ade5def user: Brian Curtin date: Mon Apr 16 15:24:02 2012 -0500 summary: Correct warnings when building the docs for the nonexistet :arg: role. Changed to asterisks. files: Doc/library/gc.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -187,23 +187,23 @@ A list of callbacks that will be invoked by the garbage collector before and after collection. The callbacks will be called with two arguments, - :arg:`phase` and :arg:`info`. + *phase* and *info*. - :arg:`phase` can one of two values: + *phase* can one of two values: "start": The garbage collection is about to start. "stop": The garbage collection has finished. - :arg:`info` provides more information for the callback. The following + *info* provides more information for the callback. The following keys are currently defined: "generation": The oldest generation being collected. - "collected": When :arg:`phase` is "stop", the number of objects + "collected": When *phase* is "stop", the number of objects successfully collected. - "uncollectable": when :arg:`phase` is "stop", the number of objects + "uncollectable": when *phase* is "stop", the number of objects that could not be collected and were put in :data:`garbage`. Applications can add their own callbacks to this list. The primary -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 01:14:17 2012 From: python-checkins at python.org (brian.curtin) Date: Tue, 17 Apr 2012 01:14:17 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Add_versionadded_tags_to_ne?= =?utf8?q?wly_added_ImportError_convenience_functions=2E?= Message-ID: http://hg.python.org/cpython/rev/d79aa61ec96d changeset: 76365:d79aa61ec96d user: Brian Curtin date: Mon Apr 16 18:14:09 2012 -0500 summary: Add versionadded tags to newly added ImportError convenience functions. files: Doc/c-api/exceptions.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -235,18 +235,23 @@ *kwargs* values. If *args* is ``NULL``, an empty :func:`tuple` will be created when *exc* is created via :c:func:`PyObject_Call`. + .. versionadded:: 3.3 + .. c:function:: PyObject* PyErr_SetFromImportErrorWithName(PyObject *msg, PyObject *name) This is a convenience function to raise :exc:`ImportError`. *msg* will be set as the exception's message string, and *name* will be set as the :exc:`ImportError`'s ``name`` attribute. + .. versionadded:: 3.3 + .. c:function:: PyObject* PyErr_SetFromImportErrorWithNameAndPath(PyObject *msg, PyObject *name, PyObject *path) This is a convenience function to raise :exc:`ImportError`. *msg* will be set as the exception's message string. Both *name* and *path* will be set as the :exc:`ImportError`'s respective ``name`` and ``path`` attributes. + .. versionadded:: 3.3 .. c:function:: void PyErr_SyntaxLocationEx(char *filename, int lineno, int col_offset) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 01:41:46 2012 From: python-checkins at python.org (vinay.sajip) Date: Tue, 17 Apr 2012 01:41:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Corrected_versi?= =?utf8?q?on_numbers_in_cookbook_example=2E?= Message-ID: http://hg.python.org/cpython/rev/cf880f002f3c changeset: 76366:cf880f002f3c branch: 3.2 parent: 76352:481794505ac2 user: Vinay Sajip date: Tue Apr 17 00:40:48 2012 +0100 summary: Corrected version numbers in cookbook example. files: Doc/howto/logging-cookbook.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1554,14 +1554,14 @@ Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant section of the specification `_.) -In Python 2.6 and 2.7, code was added to +In Python 3.1, code was added to :class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but unfortunately, it was implemented incorrectly, with the BOM appearing at the beginning of the message and hence not allowing any pure-ASCII component to appear before it. As this behaviour is broken, the incorrect BOM insertion code is being removed -from Python 2.7.4 and later. However, it is not being replaced, and if you +from Python 3.2.4 and later. However, it is not being replaced, and if you want to produce RFC 5424-compliant messages which includes a BOM, an optional pure-ASCII sequence before it and arbitrary Unicode after it, encoded using UTF-8, then you need to do the following: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 01:41:47 2012 From: python-checkins at python.org (vinay.sajip) Date: Tue, 17 Apr 2012 01:41:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merged_cookbook_corrections_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/6558a6a137a5 changeset: 76367:6558a6a137a5 parent: 76365:d79aa61ec96d parent: 76366:cf880f002f3c user: Vinay Sajip date: Tue Apr 17 00:41:39 2012 +0100 summary: Merged cookbook corrections from 3.2. files: Doc/howto/logging-cookbook.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1581,14 +1581,14 @@ Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant section of the specification `_.) -In Python 2.6 and 2.7, code was added to +In Python 3.1, code was added to :class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but unfortunately, it was implemented incorrectly, with the BOM appearing at the beginning of the message and hence not allowing any pure-ASCII component to appear before it. As this behaviour is broken, the incorrect BOM insertion code is being removed -from Python 2.7.4 and later. However, it is not being replaced, and if you +from Python 3.2.4 and later. However, it is not being replaced, and if you want to produce RFC 5424-compliant messages which includes a BOM, an optional pure-ASCII sequence before it and arbitrary Unicode after it, encoded using UTF-8, then you need to do the following: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 02:48:56 2012 From: python-checkins at python.org (brett.cannon) Date: Tue, 17 Apr 2012 02:48:56 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Fix_a_log?= =?utf8?q?ic_bug=2E?= Message-ID: http://hg.python.org/cpython/rev/a8895117a38d changeset: 76368:a8895117a38d user: Brett Cannon date: Mon Apr 16 20:44:21 2012 -0400 summary: Issue #13959: Fix a logic bug. files: Lib/imp.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -45,7 +45,7 @@ """ suffix, mode, type_ = details - if mode and (not mode.startswith(('r', 'U'))) or '+' in mode: + if mode and (not mode.startswith(('r', 'U')) or '+' in mode): raise ValueError('invalid file open mode {!r}'.format(mode)) elif file is None and type_ in {PY_SOURCE, PY_COMPILED}: msg = 'file object required for import (type code {})'.format(type_) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 02:48:56 2012 From: python-checkins at python.org (brett.cannon) Date: Tue, 17 Apr 2012 02:48:56 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314599=3A_Make_test?= =?utf8?q?=5Freprlib_robust_against_import_cache_race?= Message-ID: http://hg.python.org/cpython/rev/eae7cc54d28b changeset: 76369:eae7cc54d28b user: Brett Cannon date: Mon Apr 16 20:48:50 2012 -0400 summary: Issue #14599: Make test_reprlib robust against import cache race conditions when regrtest is run with its -j option. files: Lib/test/test_reprlib.py | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_reprlib.py b/Lib/test/test_reprlib.py --- a/Lib/test/test_reprlib.py +++ b/Lib/test/test_reprlib.py @@ -213,6 +213,8 @@ # Remember where we are self.here = os.getcwd() sys.path.insert(0, self.here) + # When regrtest is run with its -j option, this command alone is not + # enough. importlib.invalidate_caches() def tearDown(self): @@ -233,6 +235,7 @@ def test_module(self): eq = self.assertEqual create_empty_file(os.path.join(self.subpkgname, self.pkgname + '.py')) + importlib.invalidate_caches() from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation eq(repr(areallylongpackageandmodulenametotestreprtruncation), "" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__)) @@ -244,6 +247,7 @@ class foo(object): pass ''') + importlib.invalidate_caches() from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import foo eq(repr(foo.foo), "" % foo.__name__) @@ -258,6 +262,7 @@ class bar: pass ''') + importlib.invalidate_caches() from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import bar # Module name may be prefixed with "test.", depending on how run. self.assertEqual(repr(bar.bar), "" % bar.__name__) @@ -267,6 +272,7 @@ class baz: pass ''') + importlib.invalidate_caches() from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import baz ibaz = baz.baz() self.assertTrue(repr(ibaz).startswith( @@ -278,6 +284,7 @@ class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: def amethod(self): pass ''') + importlib.invalidate_caches() from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux # Unbound methods first r = repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 02:50:39 2012 From: python-checkins at python.org (brett.cannon) Date: Tue, 17 Apr 2012 02:50:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314599=3A_Fix_an_im?= =?utf8?q?port_caching_race_condition=2E?= Message-ID: http://hg.python.org/cpython/rev/00a07720a570 changeset: 76370:00a07720a570 user: Brett Cannon date: Mon Apr 16 20:50:33 2012 -0400 summary: Issue #14599: Fix an import caching race condition. files: Lib/test/test_import.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -346,6 +346,7 @@ pkg_name = "extension" pkg_file = pkg_name + "{}".format("_d.pyd" if debug else ".pyd") with open(pkg_file, "w"): pass + importlib.invalidate_caches() try: with self.assertRaises(ImportError) as err: import extension -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 04:11:31 2012 From: python-checkins at python.org (brett.cannon) Date: Tue, 17 Apr 2012 04:11:31 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Re-implem?= =?utf8?q?ent_imp=2Eload=5Fsource=28=29_in_imp=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/3b5b4b4bb43c changeset: 76371:3b5b4b4bb43c user: Brett Cannon date: Mon Apr 16 22:11:25 2012 -0400 summary: Issue #13959: Re-implement imp.load_source() in imp.py. files: Lib/imp.py | 29 ++- Python/import.c | 390 ------------------------------------ 2 files changed, 28 insertions(+), 391 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -14,7 +14,7 @@ from _imp import (get_magic, get_tag, get_suffixes, cache_from_source, source_from_cache) # Should be re-implemented here (and mostly deprecated) -from _imp import (find_module, load_compiled, load_source, NullImporter, +from _imp import (find_module, load_compiled, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, PY_CODERESOURCE, IMP_HOOK) @@ -25,6 +25,33 @@ import os +class _LoadSourceCompatibility(_bootstrap._SourceFileLoader): + + """Compatibility support for implementing load_source().""" + + def __init__(self, fullname, path, file=None): + super().__init__(fullname, path) + self.file = file + + def get_data(self, path): + """Gross hack to contort SourceFileLoader to deal w/ load_source()'s bad + API.""" + if path == self._path: + with self.file: + # Technically should be returning bytes, but + # SourceLoader.get_code() just passed what is returned to + # compile() which can handle str. And converting to bytes would + # require figuring out the encoding to decode to and + # tokenize.detect_encoding() only accepts bytes. + return self.file.read() + else: + return super().get_data(path) + + +def load_source(name, pathname, file=None): + return _LoadSourceCompatibility(name, pathname, file).load_module(name) + + def load_package(name, path): if os.path.isdir(path): extensions = _bootstrap._suffix_list(PY_SOURCE) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -904,26 +904,6 @@ } -/* Like strrchr(string, '/') but searches for the rightmost of either SEP - or ALTSEP, if the latter is defined. -*/ -static Py_UCS4* -rightmost_sep(Py_UCS4 *s) -{ - Py_UCS4 *found, c; - for (found = NULL; (c = *s); s++) { - if (c == SEP -#ifdef ALTSEP - || c == ALTSEP -#endif - ) - { - found = s; - } - } - return found; -} - /* Like rightmost_sep, but operate on unicode objects. */ static Py_ssize_t rightmost_sep_obj(PyObject* o, Py_ssize_t start, Py_ssize_t end) @@ -1081,50 +1061,6 @@ return result; } -/* Given a pathname for a Python source file, its time of last - modification, and a pathname for a compiled file, check whether the - compiled file represents the same version of the source. If so, - return a FILE pointer for the compiled file, positioned just after - the header; if not, return NULL. - Doesn't set an exception. */ - -static FILE * -check_compiled_module(PyObject *pathname, struct stat *srcstat, PyObject *cpathname) -{ - FILE *fp; - long magic; - long pyc_mtime; - long pyc_size; - - fp = _Py_fopen(cpathname, "rb"); - if (fp == NULL) - return NULL; - magic = PyMarshal_ReadLongFromFile(fp); - if (magic != pyc_magic) { - if (Py_VerboseFlag) - PySys_FormatStderr("# %R has bad magic\n", cpathname); - fclose(fp); - return NULL; - } - pyc_mtime = PyMarshal_ReadLongFromFile(fp); - if (pyc_mtime != srcstat->st_mtime) { - if (Py_VerboseFlag) - PySys_FormatStderr("# %R has bad mtime\n", cpathname); - fclose(fp); - return NULL; - } - pyc_size = PyMarshal_ReadLongFromFile(fp); - if (pyc_size != (srcstat->st_size & 0xFFFFFFFF)) { - if (Py_VerboseFlag) - PySys_FormatStderr("# %R has bad size\n", cpathname); - fclose(fp); - return NULL; - } - if (Py_VerboseFlag) - PySys_FormatStderr("# %R matches %R\n", cpathname, pathname); - return fp; -} - /* Read a code object from a file and check it for validity */ @@ -1178,238 +1114,6 @@ return m; } -/* Parse a source file and return the corresponding code object */ - -static PyCodeObject * -parse_source_module(PyObject *pathname, FILE *fp) -{ - PyCodeObject *co; - PyObject *pathbytes; - mod_ty mod; - PyCompilerFlags flags; - PyArena *arena; - - pathbytes = PyUnicode_EncodeFSDefault(pathname); - if (pathbytes == NULL) - return NULL; - - arena = PyArena_New(); - if (arena == NULL) { - Py_DECREF(pathbytes); - return NULL; - } - - flags.cf_flags = 0; - mod = PyParser_ASTFromFile(fp, PyBytes_AS_STRING(pathbytes), NULL, - Py_file_input, 0, 0, &flags, - NULL, arena); - if (mod != NULL) - co = PyAST_Compile(mod, PyBytes_AS_STRING(pathbytes), NULL, arena); - else - co = NULL; - Py_DECREF(pathbytes); - PyArena_Free(arena); - return co; -} - -/* Write a compiled module to a file, placing the time of last - modification of its source into the header. - Errors are ignored, if a write error occurs an attempt is made to - remove the file. */ - -static void -write_compiled_module(PyCodeObject *co, PyObject *cpathname, - struct stat *srcstat) -{ - Py_UCS4 *cpathname_ucs4; - FILE *fp; - time_t mtime = srcstat->st_mtime; - long size = srcstat->st_size & 0xFFFFFFFF; - PyObject *cpathname_tmp; -#ifdef MS_WINDOWS /* since Windows uses different permissions */ - mode_t mode = srcstat->st_mode & ~S_IEXEC; - wchar_t *wdirname, *wpathname, *wpathname_tmp; -#else - mode_t dirmode = (srcstat->st_mode | - S_IXUSR | S_IXGRP | S_IXOTH | - S_IWUSR | S_IWGRP | S_IWOTH); - PyObject *dirbytes; - PyObject *cpathbytes, *cpathbytes_tmp; -#endif - int fd; - PyObject *dirname; - Py_UCS4 *dirsep; - int res, ok; - - /* Ensure that the __pycache__ directory exists. */ - cpathname_ucs4 = PyUnicode_AsUCS4Copy(cpathname); - if (!cpathname_ucs4) - return; - dirsep = rightmost_sep(cpathname_ucs4); - if (dirsep == NULL) { - if (Py_VerboseFlag) - PySys_FormatStderr("# no %s path found %R\n", CACHEDIR, cpathname); - return; - } - dirname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - cpathname_ucs4, - dirsep - cpathname_ucs4); - PyMem_Free(cpathname_ucs4); - if (dirname == NULL) { - PyErr_Clear(); - return; - } - -#ifdef MS_WINDOWS - wdirname = PyUnicode_AsUnicode(dirname); - if (wdirname == NULL) { - PyErr_Clear(); - return; - } - res = CreateDirectoryW(wdirname, NULL); - ok = (res != 0); - if (!ok && GetLastError() == ERROR_ALREADY_EXISTS) - ok = 1; -#else - dirbytes = PyUnicode_EncodeFSDefault(dirname); - if (dirbytes == NULL) { - PyErr_Clear(); - return; - } - res = mkdir(PyBytes_AS_STRING(dirbytes), dirmode); - Py_DECREF(dirbytes); - if (0 <= res) - ok = 1; - else - ok = (errno == EEXIST); -#endif - if (!ok) { - if (Py_VerboseFlag) - PySys_FormatStderr("# cannot create cache dir %R\n", dirname); - Py_DECREF(dirname); - return; - } - Py_DECREF(dirname); - - /* We first write to a tmp file and then take advantage - of atomic renaming (which *should* be true even under Windows). - As in importlib, we use id(something) to generate a pseudo-random - filename. mkstemp() can't be used since it doesn't allow specifying - the file access permissions. - */ - cpathname_tmp = PyUnicode_FromFormat("%U.%zd", - cpathname, (Py_ssize_t) co); - if (cpathname_tmp == NULL) { - PyErr_Clear(); - return; - } -#ifdef MS_WINDOWS - wpathname = PyUnicode_AsUnicode(cpathname); - if (wpathname == NULL) { - PyErr_Clear(); - return; - } - wpathname_tmp = PyUnicode_AsUnicode(cpathname_tmp); - if (wpathname_tmp == NULL) { - PyErr_Clear(); - return; - } - - (void)DeleteFileW(wpathname_tmp); - fd = _wopen(wpathname_tmp, - O_EXCL | O_CREAT | O_WRONLY | O_BINARY, - mode); - if (0 <= fd) - fp = fdopen(fd, "wb"); - else - fp = NULL; -#else - cpathbytes_tmp = PyUnicode_EncodeFSDefault(cpathname_tmp); - Py_DECREF(cpathname_tmp); - if (cpathbytes_tmp == NULL) { - PyErr_Clear(); - return; - } - cpathbytes = PyUnicode_EncodeFSDefault(cpathname); - if (cpathbytes == NULL) { - PyErr_Clear(); - return; - } - fd = open(PyBytes_AS_STRING(cpathbytes_tmp), - O_CREAT | O_EXCL | O_WRONLY, 0666); - if (0 <= fd) - fp = fdopen(fd, "wb"); - else - fp = NULL; -#endif - if (fp == NULL) { - if (Py_VerboseFlag) - PySys_FormatStderr( - "# can't create %R\n", cpathname); -#ifdef MS_WINDOWS - Py_DECREF(cpathname_tmp); -#else - Py_DECREF(cpathbytes); - Py_DECREF(cpathbytes_tmp); -#endif - return; - } - PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION); - /* First write a 0 for mtime and size */ - PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION); - PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION); - PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION); - fflush(fp); - /* Now write the true mtime and size (as 32-bit fields) */ - fseek(fp, 4L, 0); - assert(mtime <= 0xFFFFFFFF); - PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); - PyMarshal_WriteLongToFile(size, fp, Py_MARSHAL_VERSION); - if (fflush(fp) != 0 || ferror(fp)) { - if (Py_VerboseFlag) - PySys_FormatStderr("# can't write %R\n", cpathname); - /* Don't keep partial file */ - fclose(fp); -#ifdef MS_WINDOWS - (void)DeleteFileW(wpathname_tmp); - Py_DECREF(cpathname_tmp); -#else - (void) unlink(PyBytes_AS_STRING(cpathbytes_tmp)); - Py_DECREF(cpathbytes); - Py_DECREF(cpathbytes_tmp); -#endif - return; - } - fclose(fp); - /* Do a (hopefully) atomic rename */ -#ifdef MS_WINDOWS - if (!MoveFileExW(wpathname_tmp, wpathname, MOVEFILE_REPLACE_EXISTING)) { - if (Py_VerboseFlag) - PySys_FormatStderr("# can't write %R\n", cpathname); - /* Don't keep tmp file */ - (void) DeleteFileW(wpathname_tmp); - Py_DECREF(cpathname_tmp); - return; - } - Py_DECREF(cpathname_tmp); -#else - if (rename(PyBytes_AS_STRING(cpathbytes_tmp), - PyBytes_AS_STRING(cpathbytes))) { - if (Py_VerboseFlag) - PySys_FormatStderr("# can't write %R\n", cpathname); - /* Don't keep tmp file */ - unlink(PyBytes_AS_STRING(cpathbytes_tmp)); - Py_DECREF(cpathbytes); - Py_DECREF(cpathbytes_tmp); - return; - } - Py_DECREF(cpathbytes); - Py_DECREF(cpathbytes_tmp); -#endif - if (Py_VerboseFlag) - PySys_FormatStderr("# wrote %R\n", cpathname); -} - static void update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname) { @@ -1474,76 +1178,6 @@ Py_RETURN_NONE; } -/* Load a source module from a given file and return its module - object WITH INCREMENTED REFERENCE COUNT. If there's a matching - byte-compiled file, use that instead. */ - -static PyObject * -load_source_module(PyObject *name, PyObject *pathname, FILE *fp) -{ - struct stat st; - FILE *fpc; - PyObject *cpathname = NULL, *cpathbytes = NULL; - PyCodeObject *co; - PyObject *m = NULL; - - if (fstat(fileno(fp), &st) != 0) { - PyErr_Format(PyExc_RuntimeError, - "unable to get file status from %R", - pathname); - goto error; - } - if (sizeof st.st_mtime > 4) { - /* Python's .pyc timestamp handling presumes that the timestamp fits - in 4 bytes. Since the code only does an equality comparison, - ordering is not important and we can safely ignore the higher bits - (collisions are extremely unlikely). - */ - st.st_mtime &= 0xFFFFFFFF; - } - if (PyUnicode_READY(pathname) < 0) - return NULL; - cpathname = make_compiled_pathname(pathname, !Py_OptimizeFlag); - - if (cpathname != NULL) - fpc = check_compiled_module(pathname, &st, cpathname); - else - fpc = NULL; - - if (fpc) { - co = read_compiled_module(cpathname, fpc); - fclose(fpc); - if (co == NULL) - goto error; - update_compiled_module(co, pathname); - if (Py_VerboseFlag) - PySys_FormatStderr("import %U # precompiled from %R\n", - name, cpathname); - m = PyImport_ExecCodeModuleObject(name, (PyObject *)co, - cpathname, cpathname); - } - else { - co = parse_source_module(pathname, fp); - if (co == NULL) - goto error; - if (Py_VerboseFlag) - PySys_FormatStderr("import %U # from %R\n", - name, pathname); - if (cpathname != NULL) { - PyObject *ro = PySys_GetObject("dont_write_bytecode"); - if (ro == NULL || !PyObject_IsTrue(ro)) - write_compiled_module(co, cpathname, &st); - } - m = PyImport_ExecCodeModuleObject(name, (PyObject *)co, - pathname, cpathname); - } - Py_DECREF(co); - -error: - Py_XDECREF(cpathbytes); - Py_XDECREF(cpathname); - return m; -} /* Get source file -> unicode or None * Returns the path to the py file if available, else the given path @@ -3427,29 +3061,6 @@ #endif /* HAVE_DYNAMIC_LOADING */ static PyObject * -imp_load_source(PyObject *self, PyObject *args) -{ - PyObject *name, *pathname; - PyObject *fob = NULL; - PyObject *m; - FILE *fp; - if (!PyArg_ParseTuple(args, "UO&|O:load_source", - &name, - PyUnicode_FSDecoder, &pathname, - &fob)) - return NULL; - fp = get_file(pathname, fob, "r"); - if (fp == NULL) { - Py_DECREF(pathname); - return NULL; - } - m = load_source_module(name, pathname, fp); - Py_DECREF(pathname); - fclose(fp); - return m; -} - -static PyObject * imp_reload(PyObject *self, PyObject *v) { return PyImport_ReloadModule(v); @@ -3600,7 +3211,6 @@ #ifdef HAVE_DYNAMIC_LOADING {"load_dynamic", imp_load_dynamic, METH_VARARGS}, #endif - {"load_source", imp_load_source, METH_VARARGS}, {"_fix_co_filename", imp_fix_co_filename, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 05:11:34 2012 From: python-checkins at python.org (brett.cannon) Date: Tue, 17 Apr 2012 05:11:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Properly_guard_against_spec?= =?utf8?q?ial-casing=2E?= Message-ID: http://hg.python.org/cpython/rev/735d3e1e5ca2 changeset: 76372:735d3e1e5ca2 user: Brett Cannon date: Mon Apr 16 23:11:28 2012 -0400 summary: Properly guard against special-casing. files: Lib/imp.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -36,7 +36,7 @@ def get_data(self, path): """Gross hack to contort SourceFileLoader to deal w/ load_source()'s bad API.""" - if path == self._path: + if self.file and path == self._path: with self.file: # Technically should be returning bytes, but # SourceLoader.get_code() just passed what is returned to -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Apr 17 05:33:59 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 17 Apr 2012 05:33:59 +0200 Subject: [Python-checkins] Daily reference leaks (00a07720a570): sum=-2 Message-ID: results for 00a07720a570 on branch "default" -------------------------------------------- test_support leaked [0, 0, -2] references, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogieBKpI', '-x'] From python-checkins at python.org Tue Apr 17 05:34:49 2012 From: python-checkins at python.org (ezio.melotti) Date: Tue, 17 Apr 2012 05:34:49 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_=2314603=3A_use_a_listcomp_?= =?utf8?q?in_ZipFile=2Enamelist=2E?= Message-ID: http://hg.python.org/cpython/rev/cac63f6ad252 changeset: 76373:cac63f6ad252 user: Ezio Melotti date: Mon Apr 16 21:34:24 2012 -0600 summary: #14603: use a listcomp in ZipFile.namelist. files: Lib/zipfile.py | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-) diff --git a/Lib/zipfile.py b/Lib/zipfile.py --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -836,10 +836,7 @@ def namelist(self): """Return a list of file names in the archive.""" - l = [] - for data in self.filelist: - l.append(data.filename) - return l + return [data.filename for data in self.filelist] def infolist(self): """Return a list of class ZipInfo instances for files in the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 13:42:13 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 17 Apr 2012 13:42:13 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_cleanup_pseudo-code?= =?utf8?q?=3B_mention_clock=5Fgetcpuclockid=28=29?= Message-ID: http://hg.python.org/peps/rev/353f27792430 changeset: 4257:353f27792430 user: Victor Stinner date: Tue Apr 17 13:42:05 2012 +0200 summary: PEP 418: cleanup pseudo-code; mention clock_getcpuclockid() * Write _win_perf_counter() to factorize and simplify clock() and process_time() pseudo-code * Don't use os.times() but _time.times() to not have to check for the platform * clock() retries QueryPerformanceCounter() each time it is called, even if it failed files: pep-0418.txt | 65 ++++++++++++++++++--------------------- 1 files changed, 30 insertions(+), 35 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -183,20 +183,22 @@ Pseudo-code:: + if os.name == 'nt': + def _win_perf_counter(): + if _win_perf_counter.frequency is None: + _win_perf_counter.frequency = _time.QueryPerformanceFrequency() + return _time.QueryPerformanceCounter() / _win_perf_counter.frequency + _win_perf_counter.frequency = None + def perf_counter(): if perf_counter.use_performance_counter: - if perf_counter.performance_frequency is None: - try: - perf_counter.performance_frequency = _time.QueryPerformanceFrequency() - except OSError: - # QueryPerformanceFrequency() fails if the installed - # hardware does not support a high-resolution performance - # counter - perf_counter.use_performance_counter = False - else: - return _time.QueryPerformanceCounter() / perf_counter.performance_frequency - else: - return _time.QueryPerformanceCounter() / perf_counter.performance_frequency + try: + return _win_perf_counter() + except OSError: + # QueryPerformanceFrequency() fails if the installed + # hardware does not support a high-resolution performance + # counter + perf_counter.use_performance_counter = False if perf_counter.use_monotonic: # The monotonic clock is preferred over the system time try: @@ -205,8 +207,6 @@ perf_counter.use_monotonic = False return time.time() perf_counter.use_performance_counter = (os.name == 'nt') - if perf_counter.use_performance_counter: - perf_counter.performance_frequency = None perf_counter.use_monotonic = hasattr(time, 'monotonic') @@ -229,7 +229,6 @@ process_times = win32process.GetProcessTimes(handle) return (process_times['UserTime'] + process_times['KernelTime']) * 1e-7 else: - import os try: import resource except ImportError: @@ -251,8 +250,9 @@ process_time.use_getrusage = False if process_time.use_times: try: - times = os.times() - return times[0] + times[1] + times = _time.times() + cpu_time = times.tms_utime + times.tms_stime + return cpu_time / process_time.ticks_per_seconds except OSError: process_time.use_getrusage = False return _time.clock() @@ -260,8 +260,10 @@ hasattr(time, 'clock_gettime') and hasattr(time, 'CLOCK_PROCESS_CPUTIME_ID')) process_time.use_getrusage = has_resource - # On OS/2, only the 5th field of os.times() is set, others are zeros - process_time.use_times = (hasattr(os, 'times') and os.name != 'os2') + process_time.use_times = hasattr(_time, 'times') + if process_time.use_times: + # sysconf("SC_CLK_TCK"), or the HZ constant, or 60 + process_time.ticks_per_seconds = _times.ticks_per_seconds Existing Functions @@ -370,22 +372,14 @@ if os.name == 'nt': def clock(): - if clock.use_performance_counter: - if clock.perf_frequency is None: - try: - clock.perf_frequency = float(_time.QueryPerformanceFrequency()) - except OSError: - # QueryPerformanceFrequency() fails if the installed - # hardware does not support a high-resolution performance - # counter - clock.use_performance_counter = False - else: - return _time.QueryPerformanceCounter() / clock.perf_frequency - else: - return _time.QueryPerformanceCounter() / clock.perf_frequency + try: + return _win_perf_counter() + except OSError: + # QueryPerformanceFrequency() fails if the installed + # hardware does not support a high-resolution performance + # counter + pass return _time.clock() - clock.use_performance_counter = True - clock.perf_frequency = None else: clock = _time.clock @@ -1259,7 +1253,8 @@ See also the `QueryProcessCycleTime() function `_ -(sum of the cycle time of all threads). +(sum of the cycle time of all threads) and `clock_getcpuclockid() +`_. Thread Time -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 17 13:55:12 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 17 Apr 2012 13:55:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Speed_up_reading_of_small_f?= =?utf8?q?iles=2E__This_avoids_multiple_C_read=28=29_calls_on_pyc?= Message-ID: http://hg.python.org/cpython/rev/ed954d11dadd changeset: 76374:ed954d11dadd user: Antoine Pitrou date: Tue Apr 17 13:50:58 2012 +0200 summary: Speed up reading of small files. This avoids multiple C read() calls on pyc files. files: Modules/_io/fileio.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -572,6 +572,7 @@ #endif ) { + size_t addend; #ifdef HAVE_FSTAT if (end != (Py_off_t)-1) { /* Files claiming a size smaller than SMALLCHUNK may @@ -589,9 +590,16 @@ } #endif /* Expand the buffer by an amount proportional to the current size, - giving us amortized linear-time behavior. Use a less-than-double - growth factor to avoid excessive allocation. */ - return currentsize + (currentsize >> 3) + 6; + giving us amortized linear-time behavior. For bigger sizes, use a + less-than-double growth factor to avoid excessive allocation. */ + if (currentsize > 65536) + addend = currentsize >> 3; + else + addend = 256 + currentsize; + if (addend < SMALLCHUNK) + /* Avoid tiny read() calls. */ + addend = SMALLCHUNK; + return addend + currentsize; } static PyObject * -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 18:46:44 2012 From: python-checkins at python.org (charles-francois.natali) Date: Tue, 17 Apr 2012 18:46:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314087=3A_multiproc?= =?utf8?q?essing=3A_add_Condition=2Ewait=5Ffor=28=29=2E_Patch_by_sbt=2E?= Message-ID: http://hg.python.org/cpython/rev/5606ee052783 changeset: 76375:5606ee052783 user: Charles-Fran?ois Natali date: Tue Apr 17 18:45:57 2012 +0200 summary: Issue #14087: multiprocessing: add Condition.wait_for(). Patch by sbt. files: Doc/library/multiprocessing.rst | 6 + Lib/multiprocessing/managers.py | 19 +++++ Lib/multiprocessing/synchronize.py | 19 +++++ Lib/test/test_multiprocessing.py | 67 ++++++++++++++++++ Misc/NEWS | 2 + 5 files changed, 113 insertions(+), 0 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -897,6 +897,9 @@ If *lock* is specified then it should be a :class:`Lock` or :class:`RLock` object from :mod:`multiprocessing`. + .. versionchanged:: 3.3 + The :meth:`wait_for` method was added. + .. class:: Event() A clone of :class:`threading.Event`. @@ -1281,6 +1284,9 @@ If *lock* is supplied then it should be a proxy for a :class:`threading.Lock` or :class:`threading.RLock` object. + .. versionchanged:: 3.3 + The :meth:`wait_for` method was added. + .. method:: Event() Create a shared :class:`threading.Event` object and return a proxy for it. diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -48,6 +48,7 @@ from multiprocessing import Process, current_process, active_children, Pool, util, connection from multiprocessing.process import AuthenticationString from multiprocessing.forking import exit, Popen, ForkingPickler +from time import time as _time # # Register some things for pickling @@ -996,6 +997,24 @@ return self._callmethod('notify') def notify_all(self): return self._callmethod('notify_all') + def wait_for(self, predicate, timeout=None): + result = predicate() + if result: + return result + if timeout is not None: + endtime = _time() + timeout + else: + endtime = None + waittime = None + while not result: + if endtime is not None: + waittime = endtime - _time() + if waittime <= 0: + break + self.wait(waittime) + result = predicate() + return result + class EventProxy(BaseProxy): _exposed_ = ('is_set', 'set', 'clear', 'wait') diff --git a/Lib/multiprocessing/synchronize.py b/Lib/multiprocessing/synchronize.py --- a/Lib/multiprocessing/synchronize.py +++ b/Lib/multiprocessing/synchronize.py @@ -43,6 +43,7 @@ from multiprocessing.process import current_process from multiprocessing.util import register_after_fork, debug from multiprocessing.forking import assert_spawning, Popen +from time import time as _time # Try to import the mp.synchronize module cleanly, if it fails # raise ImportError for platforms lacking a working sem_open implementation. @@ -290,6 +291,24 @@ while self._wait_semaphore.acquire(False): pass + def wait_for(self, predicate, timeout=None): + result = predicate() + if result: + return result + if timeout is not None: + endtime = _time() + timeout + else: + endtime = None + waittime = None + while not result: + if endtime is not None: + waittime = endtime - _time() + if waittime <= 0: + break + self.wait(waittime) + result = predicate() + return result + # # Event # diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -887,6 +887,73 @@ self.assertEqual(res, False) self.assertTimingAlmostEqual(wait.elapsed, TIMEOUT1) + @classmethod + def _test_waitfor_f(cls, cond, state): + with cond: + state.value = 0 + cond.notify() + result = cond.wait_for(lambda : state.value==4) + if not result or state.value != 4: + sys.exit(1) + + @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes') + def test_waitfor(self): + # based on test in test/lock_tests.py + cond = self.Condition() + state = self.Value('i', -1) + + p = self.Process(target=self._test_waitfor_f, args=(cond, state)) + p.daemon = True + p.start() + + with cond: + result = cond.wait_for(lambda : state.value==0) + self.assertTrue(result) + self.assertEqual(state.value, 0) + + for i in range(4): + time.sleep(0.01) + with cond: + state.value += 1 + cond.notify() + + p.join(5) + self.assertFalse(p.is_alive()) + self.assertEqual(p.exitcode, 0) + + @classmethod + def _test_waitfor_timeout_f(cls, cond, state, success): + with cond: + expected = 0.1 + dt = time.time() + result = cond.wait_for(lambda : state.value==4, timeout=expected) + dt = time.time() - dt + # borrow logic in assertTimeout() from test/lock_tests.py + if not result and expected * 0.6 < dt < expected * 10.0: + success.value = True + + @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes') + def test_waitfor_timeout(self): + # based on test in test/lock_tests.py + cond = self.Condition() + state = self.Value('i', 0) + success = self.Value('i', False) + + p = self.Process(target=self._test_waitfor_timeout_f, + args=(cond, state, success)) + p.daemon = True + p.start() + + # Only increment 3 times, so state == 4 is never reached. + for i in range(3): + time.sleep(0.01) + with cond: + state.value += 1 + cond.notify() + + p.join(5) + self.assertTrue(success.value) + class _TestEvent(BaseTestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,8 @@ Library ------- +- Issue #14087: multiprocessing: add Condition.wait_for(). Patch by sbt. + - Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. - Issue #14386: Expose the dict_proxy internal type as types.MappingProxyType. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 19:59:29 2012 From: python-checkins at python.org (charles-francois.natali) Date: Tue, 17 Apr 2012 19:59:29 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzUxMTM6?= =?utf8?q?_Fix_a_test=5Fposix_failure_on_HP-UX=2C_where_non-root_users_can?= Message-ID: http://hg.python.org/cpython/rev/8a4c9a168d09 changeset: 76376:8a4c9a168d09 branch: 2.7 parent: 76351:de27fedaeb25 user: Charles-Fran?ois Natali date: Tue Apr 17 19:46:06 2012 +0200 summary: Issue #5113: Fix a test_posix failure on HP-UX, where non-root users can chown() to root under certain circumstances. files: Lib/test/test_posix.py | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -9,6 +9,7 @@ import sys import time import os +import platform import pwd import shutil import stat @@ -219,6 +220,9 @@ def _test_all_chown_common(self, chown_func, first_param): """Common code for chown, fchown and lchown tests.""" + # test a successful chown call + chown_func(first_param, os.getuid(), os.getgid()) + if os.getuid() == 0: try: # Many linux distros have a nfsnobody user as MAX_UID-2 @@ -230,14 +234,16 @@ chown_func(first_param, ent.pw_uid, ent.pw_gid) except KeyError: pass + elif platform.system() in ('HP-UX', 'SunOS'): + # HP-UX and Solaris can allow a non-root user to chown() to root + # (issue #5113) + raise unittest.SkipTest("Skipping because of non-standard chown() " + "behavior") else: # non-root cannot chown to root, raises OSError self.assertRaises(OSError, chown_func, first_param, 0, 0) - # test a successful chown call - chown_func(first_param, os.getuid(), os.getgid()) - @unittest.skipUnless(hasattr(posix, 'chown'), "test needs os.chown()") def test_chown(self): # raise an OSError if the file does not exist -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 19:59:31 2012 From: python-checkins at python.org (charles-francois.natali) Date: Tue, 17 Apr 2012 19:59:31 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzUxMTM6?= =?utf8?q?_Fix_a_test=5Fposix_failure_on_HP-UX=2C_where_non-root_users_can?= Message-ID: http://hg.python.org/cpython/rev/428bece48029 changeset: 76377:428bece48029 branch: 3.2 parent: 76366:cf880f002f3c user: Charles-Fran?ois Natali date: Tue Apr 17 19:48:35 2012 +0200 summary: Issue #5113: Fix a test_posix failure on HP-UX, where non-root users can chown() to root under certain circumstances. files: Lib/test/test_posix.py | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -9,6 +9,7 @@ import sys import time import os +import platform import pwd import shutil import stat @@ -229,6 +230,9 @@ def _test_all_chown_common(self, chown_func, first_param): """Common code for chown, fchown and lchown tests.""" + # test a successful chown call + chown_func(first_param, os.getuid(), os.getgid()) + if os.getuid() == 0: try: # Many linux distros have a nfsnobody user as MAX_UID-2 @@ -240,12 +244,15 @@ chown_func(first_param, ent.pw_uid, ent.pw_gid) except KeyError: pass + elif platform.system() in ('HP-UX', 'SunOS'): + # HP-UX and Solaris can allow a non-root user to chown() to root + # (issue #5113) + raise unittest.SkipTest("Skipping because of non-standard chown() " + "behavior") else: # non-root cannot chown to root, raises OSError self.assertRaises(OSError, chown_func, first_param, 0, 0) - # test a successful chown call - chown_func(first_param, os.getuid(), os.getgid()) @unittest.skipUnless(hasattr(posix, 'chown'), "test needs os.chown()") def test_chown(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 19:59:32 2012 From: python-checkins at python.org (charles-francois.natali) Date: Tue, 17 Apr 2012 19:59:32 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=235113=3A_Fix_a_test=5Fposix_failure_on_HP-UX=2C_wher?= =?utf8?q?e_non-root_users_can?= Message-ID: http://hg.python.org/cpython/rev/3d4922cf0d65 changeset: 76378:3d4922cf0d65 parent: 76375:5606ee052783 parent: 76377:428bece48029 user: Charles-Fran?ois Natali date: Tue Apr 17 19:58:50 2012 +0200 summary: Issue #5113: Fix a test_posix failure on HP-UX, where non-root users can chown() to root under certain circumstances. files: Lib/test/test_posix.py | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -10,6 +10,7 @@ import time import os import fcntl +import platform import pwd import shutil import stat @@ -390,6 +391,9 @@ def _test_all_chown_common(self, chown_func, first_param): """Common code for chown, fchown and lchown tests.""" + # test a successful chown call + chown_func(first_param, os.getuid(), os.getgid()) + if os.getuid() == 0: try: # Many linux distros have a nfsnobody user as MAX_UID-2 @@ -401,12 +405,15 @@ chown_func(first_param, ent.pw_uid, ent.pw_gid) except KeyError: pass + elif platform.system() in ('HP-UX', 'SunOS'): + # HP-UX and Solaris can allow a non-root user to chown() to root + # (issue #5113) + raise unittest.SkipTest("Skipping because of non-standard chown() " + "behavior") else: # non-root cannot chown to root, raises OSError self.assertRaises(OSError, chown_func, first_param, 0, 0) - # test a successful chown call - chown_func(first_param, os.getuid(), os.getgid()) @unittest.skipUnless(hasattr(posix, 'chown'), "test needs os.chown()") def test_chown(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 23:40:58 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 17 Apr 2012 23:40:58 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_clock=5Fprecision?= =?utf8?q?=2Epy_only_uses_ASCII_to_avoid_UnicodeEncodeError_on?= Message-ID: http://hg.python.org/peps/rev/9d083c475fd0 changeset: 4258:9d083c475fd0 user: Victor Stinner date: Tue Apr 17 23:40:47 2012 +0200 summary: PEP 418: clock_precision.py only uses ASCII to avoid UnicodeEncodeError on print() files: pep-0418/clock_precision.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_precision.py --- a/pep-0418/clock_precision.py +++ b/pep-0418/clock_precision.py @@ -26,7 +26,7 @@ if dt >= 1e-3: return "%.0f ms" % (dt * 1e3) if dt >= 1e-6: - return "%.0f ?s" % (dt * 1e6) + return "%.0f us" % (dt * 1e6) else: return "%.0f ns" % (dt * 1e9) -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 17 23:57:24 2012 From: python-checkins at python.org (brian.curtin) Date: Tue, 17 Apr 2012 23:57:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_=2314600=2E_Correct_ref?= =?utf8?q?erence_handling_and_naming_of_ImportError_convenience?= Message-ID: http://hg.python.org/cpython/rev/7a32b9380ffd changeset: 76379:7a32b9380ffd user: Brian Curtin date: Tue Apr 17 16:57:09 2012 -0500 summary: Fix #14600. Correct reference handling and naming of ImportError convenience function files: Doc/c-api/exceptions.rst | 23 +--------- Include/pyerrors.h | 5 +- Python/dynload_win.c | 6 +- Python/errors.c | 59 ++++++++++++--------------- Python/import.c | 3 +- 5 files changed, 37 insertions(+), 59 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -229,27 +229,12 @@ Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, with an additional parameter specifying the exception type to be raised. Availability: Windows. -.. c:function:: PyObject* PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs) - - This is a convenience function to set an *exc* with the given *args* and - *kwargs* values. If *args* is ``NULL``, an empty :func:`tuple` will be - created when *exc* is created via :c:func:`PyObject_Call`. - - .. versionadded:: 3.3 - -.. c:function:: PyObject* PyErr_SetFromImportErrorWithName(PyObject *msg, PyObject *name) +.. c:function:: PyObject* PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) This is a convenience function to raise :exc:`ImportError`. *msg* will be - set as the exception's message string, and *name* will be set as the - :exc:`ImportError`'s ``name`` attribute. - - .. versionadded:: 3.3 - -.. c:function:: PyObject* PyErr_SetFromImportErrorWithNameAndPath(PyObject *msg, PyObject *name, PyObject *path) - - This is a convenience function to raise :exc:`ImportError`. *msg* will be - set as the exception's message string. Both *name* and *path* will be set - as the :exc:`ImportError`'s respective ``name`` and ``path`` attributes. + set as the exception's message string. *name* and *path*, both of which can + be ``NULL``, will be set as the :exc:`ImportError`'s respective ``name`` + and ``path`` attributes. .. versionadded:: 3.3 diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -265,9 +265,8 @@ PyAPI_FUNC(PyObject *) PyErr_SetExcWithArgsKwargs(PyObject *, PyObject *, PyObject *); -PyAPI_FUNC(PyObject *) PyErr_SetFromImportErrorWithNameAndPath(PyObject *, - PyObject *, PyObject *); -PyAPI_FUNC(PyObject *) PyErr_SetFromImportErrorWithName(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyErr_SetImportError(PyObject *, PyObject *, + PyObject *); /* Export the old function so that the existing API remains available: */ PyAPI_FUNC(void) PyErr_BadInternalCall(void); diff --git a/Python/dynload_win.c b/Python/dynload_win.c --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -254,9 +254,9 @@ theLength)); } if (message != NULL) { - PyErr_SetFromImportErrorWithNameAndPath(message, - PyUnicode_FromString(shortname), - pathname); + PyErr_SetImportError(message, PyUnicode_FromString(shortname), + pathname); + Py_DECREF(message); } return NULL; } else { diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -586,50 +586,43 @@ #endif /* MS_WINDOWS */ PyObject * -PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs) +PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) { - PyObject *val; + PyObject *args, *kwargs, *error; + + args = PyTuple_New(1); + if (args == NULL) + return NULL; + + kwargs = PyDict_New(); + if (args == NULL) + return NULL; + + if (name == NULL) + name = Py_None; + + if (path == NULL) + path = Py_None; + + Py_INCREF(msg); + PyTuple_SetItem(args, 0, msg); + PyDict_SetItemString(kwargs, "name", name); + PyDict_SetItemString(kwargs, "path", path); /* args must at least be an empty tuple */ if (args == NULL) args = PyTuple_New(0); - val = PyObject_Call(exc, args, kwargs); - if (val != NULL) { - PyErr_SetObject((PyObject *) Py_TYPE(val), val); - Py_DECREF(val); + error = PyObject_Call(PyExc_ImportError, args, kwargs); + if (error!= NULL) { + PyErr_SetObject((PyObject *) Py_TYPE(error), error); + Py_DECREF(error); } - return NULL; -} - -PyObject * -PyErr_SetFromImportErrorWithNameAndPath(PyObject *msg, - PyObject *name, PyObject *path) -{ - PyObject *args = PyTuple_New(1); - PyObject *kwargs = PyDict_New(); - PyObject *result; - - if (path == NULL) - path = Py_None; - - PyTuple_SetItem(args, 0, msg); - PyDict_SetItemString(kwargs, "name", name); - PyDict_SetItemString(kwargs, "path", path); - - result = PyErr_SetExcWithArgsKwargs(PyExc_ImportError, args, kwargs); - Py_DECREF(args); Py_DECREF(kwargs); - return result; -} - -PyObject * -PyErr_SetFromImportErrorWithName(PyObject *msg, PyObject *name) -{ - return PyErr_SetFromImportErrorWithNameAndPath(msg, name, NULL); + return NULL; } void diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2460,7 +2460,8 @@ PyObject *msg = PyUnicode_FromFormat("import of %R halted; " "None in sys.modules", abs_name); if (msg != NULL) { - PyErr_SetFromImportErrorWithName(msg, abs_name); + PyErr_SetImportError(msg, abs_name, NULL); + Py_DECREF(msg); } mod = NULL; goto error_with_unlock; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 17 23:59:40 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 17 Apr 2012 23:59:40 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_benchmark_resul?= =?utf8?q?ts_of_Mac_OS_10=2E6?= Message-ID: http://hg.python.org/peps/rev/bbc58fd41f78 changeset: 4259:bbc58fd41f78 user: Victor Stinner date: Tue Apr 17 23:59:33 2012 +0200 summary: PEP 418: Add benchmark results of Mac OS 10.6 Fix also clock_precision.py: catch clock_gettime() errors files: pep-0418.txt | 12 +++++++++--- pep-0418/clock_precision.py | 5 +++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -902,11 +902,12 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== -CLOCK_HIGHRES SunOS 5.11 2 ns 2 ?s +CLOCK_HIGHRES SunOS 5.11 2 ns 253 ns CLOCK_MONOTONIC Linux 3.2 1 ns 2 ?s CLOCK_MONOTONIC SunOS 5.11 2 ns 3 ?s CLOCK_MONOTONIC_RAW Linux 3.2 1 ns 3 ?s CLOCK_BOOTTIME Linux 3.3 1 ns 3 ?s +mach_absolute_time() Mac OS 10.6 1 ns 3 ?s CLOCK_MONOTONIC FreeBSD 8.2 11 ns 7 ?s CLOCK_MONOTONIC OpenBSD 5.0 10 ms 7 ?s QueryPerformanceCounter Windows Seven 10 ns 9 ?s @@ -1151,8 +1152,9 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== -CLOCK_REALTIME SunOS 5.11 10 ms 2 ?s +CLOCK_REALTIME SunOS 5.11 10 ms 238 ns CLOCK_REALTIME Linux 3.2 1 ns 2 ?s +gettimeofday() Mac OS 10.6 1 ?s 4 ?s CLOCK_REALTIME FreeBSD 8.2 11 ns 7 ?s CLOCK_REALTIME OpenBSD 5.0 10 ms 10 ?s CLOCK_REALTIME_COARSE Linux 3.3 1 ms 1 ms @@ -1212,9 +1214,12 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== +CLOCK_PROF FreeBSD 8.2 10 ms 1 ?s getrusage(RUSAGE_SELF) FreeBSD 8.2 \- 1 ?s CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns 3 ?s -getrusage(RUSAGE_SELF) SunOS 5.11 \- 3 ?s +getrusage(RUSAGE_SELF) SunOS 5.11 \- 1 ?s +getrusage(RUSAGE_SELF) Mac OS 10.6 \- 5 ?s +clock() Mac OS 10.6 1 ?s 5 ?s getrusage(RUSAGE_SELF) Linux 3.3 \- 1 ms getrusage(RUSAGE_SELF) OpenBSD 5.0 \- 8 ms clock() FreeBSD 8.2 8 ms 8 ms @@ -1222,6 +1227,7 @@ times() Linux 3.0 10 ms 10 ms clock() OpenBSD 5.0 10 ms 10 ms times() OpenBSD 5.0 10 ms 10 ms +times() Mac OS 10.6 10 ms 10 ms GetProcessTimes() Windows Seven 16 ms 16 ms clock() SunOS 5.11 1 ?s 10 ms ========================= ================ ========= =================== diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_precision.py --- a/pep-0418/clock_precision.py +++ b/pep-0418/clock_precision.py @@ -51,6 +51,11 @@ name = 'clock_gettime(%s)' % clock_id_text def gettime(): return time.clock_gettime(clock_id) + try: + gettime() + except OSError as err: + print("%s failed: %s" % (name, err)) + continue test_clock(name, gettime) precision = time.clock_getres(clock_id) print("- announced precision: %s" % format_duration(precision)) -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 00:39:08 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 00:39:08 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_clock=5Fprecisi?= =?utf8?q?on=2Epy=2C_time=2Emonotonic=28=29_is_not_always_present?= Message-ID: http://hg.python.org/peps/rev/9496665d7e5f changeset: 4260:9496665d7e5f user: Victor Stinner date: Wed Apr 18 00:39:03 2012 +0200 summary: PEP 418: Fix clock_precision.py, time.monotonic() is not always present files: pep-0418/clock_precision.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_precision.py --- a/pep-0418/clock_precision.py +++ b/pep-0418/clock_precision.py @@ -36,7 +36,11 @@ print("- precision in Python: %s" % format_duration(precision)) -for name in ('clock', 'perf_counter', 'process_time', 'monotonic', 'time'): +clocks = ('clock', 'perf_counter', 'process_time') +if hasattr(time, 'monotonic'): + clocks.append('monotonic') +clocks.append('time') +for name in clocks: func = getattr(time, name) test_clock("%s()" % name, func) info = time.get_clock_info(name) -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 00:39:42 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 00:39:42 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Oops=2C_fix_typo_in?= =?utf8?q?_last_commit?= Message-ID: http://hg.python.org/peps/rev/77e1aaecd7b4 changeset: 4261:77e1aaecd7b4 user: Victor Stinner date: Wed Apr 18 00:39:39 2012 +0200 summary: PEP 418: Oops, fix typo in last commit files: pep-0418/clock_precision.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_precision.py --- a/pep-0418/clock_precision.py +++ b/pep-0418/clock_precision.py @@ -36,7 +36,7 @@ print("- precision in Python: %s" % format_duration(precision)) -clocks = ('clock', 'perf_counter', 'process_time') +clocks = ['clock', 'perf_counter', 'process_time'] if hasattr(time, 'monotonic'): clocks.append('monotonic') clocks.append('time') -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 01:05:20 2012 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2012 01:05:20 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314592=3A_A_relativ?= =?utf8?q?e_import_will_raise_a_KeyError_if_=5F=5Fpackage=5F=5F?= Message-ID: http://hg.python.org/cpython/rev/68f9ad6a3b13 changeset: 76380:68f9ad6a3b13 user: Brett Cannon date: Tue Apr 17 19:05:11 2012 -0400 summary: Issue #14592: A relative import will raise a KeyError if __package__ or __name__ are not set in globals. Thanks to Stefan Behnel for the bug report. files: Lib/importlib/test/import_/test_relative_imports.py | 5 +++++ Misc/NEWS | 3 +++ Python/import.c | 3 ++- 3 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Lib/importlib/test/import_/test_relative_imports.py b/Lib/importlib/test/import_/test_relative_imports.py --- a/Lib/importlib/test/import_/test_relative_imports.py +++ b/Lib/importlib/test/import_/test_relative_imports.py @@ -203,6 +203,11 @@ self.assertEqual(mod.__name__, 'crash.mod') self.relative_import_test(create, globals_, callback) + def test_relative_import_no_globals(self): + # No globals for a relative import is an error. + with self.assertRaises(KeyError): + import_util.import_('sys', level=1) + def test_main(): from test.support import run_unittest diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14592: Attempting a relative import w/o __package__ or __name__ set in + globals raises a KeyError. + - Issue #10854: The ImportError raised when an extension module on Windows fails to import now uses the new path and name attributes from Issue #1559549. diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2355,8 +2355,9 @@ } } else { - package = _PyDict_GetItemIdWithError(globals, &PyId___name__); + package = _PyDict_GetItemId(globals, &PyId___name__); if (package == NULL) { + PyErr_SetString(PyExc_KeyError, "'__name__' not in globals"); goto error; } else if (!PyUnicode_Check(package)) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 01:14:32 2012 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2012 01:14:32 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Re-implem?= =?utf8?q?ent_imp=2Eload=5Fcompiled=28=29_in_imp=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/66bd85bcf916 changeset: 76381:66bd85bcf916 user: Brett Cannon date: Tue Apr 17 19:14:26 2012 -0400 summary: Issue #13959: Re-implement imp.load_compiled() in imp.py. files: Lib/imp.py | 25 +++++++++-- Python/import.c | 76 ------------------------------------- 2 files changed, 20 insertions(+), 81 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -14,7 +14,7 @@ from _imp import (get_magic, get_tag, get_suffixes, cache_from_source, source_from_cache) # Should be re-implemented here (and mostly deprecated) -from _imp import (find_module, load_compiled, NullImporter, +from _imp import (find_module, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, PY_CODERESOURCE, IMP_HOOK) @@ -25,17 +25,17 @@ import os -class _LoadSourceCompatibility(_bootstrap._SourceFileLoader): +class _HackedGetData: - """Compatibility support for implementing load_source().""" + """Compatibiilty support for 'file' arguments of various load_*() + functions.""" def __init__(self, fullname, path, file=None): super().__init__(fullname, path) self.file = file def get_data(self, path): - """Gross hack to contort SourceFileLoader to deal w/ load_source()'s bad - API.""" + """Gross hack to contort loader to deal w/ load_*()'s bad API.""" if self.file and path == self._path: with self.file: # Technically should be returning bytes, but @@ -48,10 +48,25 @@ return super().get_data(path) +class _LoadSourceCompatibility(_HackedGetData, _bootstrap._SourceFileLoader): + + """Compatibility support for implementing load_source().""" + + def load_source(name, pathname, file=None): return _LoadSourceCompatibility(name, pathname, file).load_module(name) +class _LoadCompiledCompatibility(_HackedGetData, + _bootstrap._SourcelessFileLoader): + + """Compatibility support for implementing load_compiled().""" + + +def load_compiled(name, pathname, file=None): + return _LoadCompiledCompatibility(name, pathname, file).load_module(name) + + def load_package(name, path): if os.path.isdir(path): extensions = _bootstrap._suffix_list(PY_SOURCE) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1062,58 +1062,6 @@ } -/* Read a code object from a file and check it for validity */ - -static PyCodeObject * -read_compiled_module(PyObject *cpathname, FILE *fp) -{ - PyObject *co; - - co = PyMarshal_ReadLastObjectFromFile(fp); - if (co == NULL) - return NULL; - if (!PyCode_Check(co)) { - PyErr_Format(PyExc_ImportError, - "Non-code object in %R", cpathname); - Py_DECREF(co); - return NULL; - } - return (PyCodeObject *)co; -} - - -/* Load a module from a compiled file, execute it, and return its - module object WITH INCREMENTED REFERENCE COUNT */ - -static PyObject * -load_compiled_module(PyObject *name, PyObject *cpathname, FILE *fp) -{ - long magic; - PyCodeObject *co; - PyObject *m; - - magic = PyMarshal_ReadLongFromFile(fp); - if (magic != pyc_magic) { - PyErr_Format(PyExc_ImportError, - "Bad magic number in %R", cpathname); - return NULL; - } - /* Skip mtime and size */ - (void) PyMarshal_ReadLongFromFile(fp); - (void) PyMarshal_ReadLongFromFile(fp); - co = read_compiled_module(cpathname, fp); - if (co == NULL) - return NULL; - if (Py_VerboseFlag) - PySys_FormatStderr("import %U # precompiled from %R\n", - name, cpathname); - m = PyImport_ExecCodeModuleObject(name, (PyObject *)co, - cpathname, cpathname); - Py_DECREF(co); - - return m; -} - static void update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname) { @@ -3010,29 +2958,6 @@ } } -static PyObject * -imp_load_compiled(PyObject *self, PyObject *args) -{ - PyObject *name, *pathname; - PyObject *fob = NULL; - PyObject *m; - FILE *fp; - if (!PyArg_ParseTuple(args, "UO&|O:load_compiled", - &name, - PyUnicode_FSDecoder, &pathname, - &fob)) - return NULL; - fp = get_file(pathname, fob, "rb"); - if (fp == NULL) { - Py_DECREF(pathname); - return NULL; - } - m = load_compiled_module(name, pathname, fp); - fclose(fp); - Py_DECREF(pathname); - return m; -} - #ifdef HAVE_DYNAMIC_LOADING static PyObject * @@ -3209,7 +3134,6 @@ {"init_frozen", imp_init_frozen, METH_VARARGS}, {"is_builtin", imp_is_builtin, METH_VARARGS}, {"is_frozen", imp_is_frozen, METH_VARARGS}, - {"load_compiled", imp_load_compiled, METH_VARARGS}, #ifdef HAVE_DYNAMIC_LOADING {"load_dynamic", imp_load_dynamic, METH_VARARGS}, #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 01:15:18 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 01:15:18 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_complete/update_tab?= =?utf8?q?les_for_OpenBSD_and_Windows?= Message-ID: http://hg.python.org/peps/rev/047dfc2552a8 changeset: 4262:047dfc2552a8 user: Victor Stinner date: Wed Apr 18 01:14:38 2012 +0200 summary: PEP 418: complete/update tables for OpenBSD and Windows files: pep-0418.txt | 15 +++++++++------ 1 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -913,7 +913,7 @@ QueryPerformanceCounter Windows Seven 10 ns 9 ?s CLOCK_UPTIME FreeBSD 8.2 11 ns 9 ?s CLOCK_MONOTONIC_COARSE Linux 3.3 1 ms 1 ms -GetTickCount Windows Seven 16 ms 15 ms +GetTickCount64() Windows Seven 16 ms 16 ms ========================= ================ ========= =================== mach_absolute_time @@ -1158,7 +1158,8 @@ CLOCK_REALTIME FreeBSD 8.2 11 ns 7 ?s CLOCK_REALTIME OpenBSD 5.0 10 ms 10 ?s CLOCK_REALTIME_COARSE Linux 3.3 1 ms 1 ms -GetSystemTimeAsFileTime Windows Seven 16 ms 1 ms +GetSystemTimeAsFileTime() Windows Seven 16 ms 1 ms +ftime() Windows Seven \- 1 ms ========================= ================ ========= =================== @@ -1216,10 +1217,11 @@ ========================= ================ ========= =================== CLOCK_PROF FreeBSD 8.2 10 ms 1 ?s getrusage(RUSAGE_SELF) FreeBSD 8.2 \- 1 ?s +getrusage(RUSAGE_SELF) SunOS 5.11 \- 1 ?s CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns 3 ?s -getrusage(RUSAGE_SELF) SunOS 5.11 \- 1 ?s getrusage(RUSAGE_SELF) Mac OS 10.6 \- 5 ?s clock() Mac OS 10.6 1 ?s 5 ?s +CLOCK_PROF OpenBSD 5.0 \- 7 ?s getrusage(RUSAGE_SELF) Linux 3.3 \- 1 ms getrusage(RUSAGE_SELF) OpenBSD 5.0 \- 8 ms clock() FreeBSD 8.2 8 ms 8 ms @@ -1228,8 +1230,9 @@ clock() OpenBSD 5.0 10 ms 10 ms times() OpenBSD 5.0 10 ms 10 ms times() Mac OS 10.6 10 ms 10 ms +clock() SunOS 5.11 1 ?s 10 ms GetProcessTimes() Windows Seven 16 ms 16 ms -clock() SunOS 5.11 1 ?s 10 ms +clock() Windows Seven 1 ms 1 ms ========================= ================ ========= =================== Functions @@ -1243,8 +1246,8 @@ * clock(). The precision is 1 / CLOCKS_PER_SEC. * Windows: The elapsed wall-clock time since the start of the - process (elapsed time in seconds times CLOCKS_PER_SEC). It can - fail. + process (elapsed time in seconds times CLOCKS_PER_SEC). Include + time elapsed during sleep. It can fail. * UNIX: returns an approximation of processor time used by the program. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 01:34:29 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 01:34:29 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_time=2Eprocess=5Fti?= =?utf8?q?me=28=29_uses_CLOCK=5FPROF_if_available?= Message-ID: http://hg.python.org/peps/rev/438a9af89329 changeset: 4263:438a9af89329 user: Victor Stinner date: Wed Apr 18 01:34:26 2012 +0200 summary: PEP 418: time.process_time() uses CLOCK_PROF if available files: pep-0418.txt | 19 ++++++++++++------- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -134,7 +134,7 @@ if os.name == 'nt': # GetTickCount64() requires Windows Vista, Server 2008 or later - if hasattr(time, '_GetTickCount64'): + if hasattr(_time, '_GetTickCount64'): def monotonic(): return _time.GetTickCount64() * 1e-3 else: @@ -237,11 +237,11 @@ has_resource = True def process_time(): - if process_time.use_process_cputime: + if process_time.clock_id is not None: try: - return time.clock_gettime(time.CLOCK_PROCESS_CPUTIME_ID) + return time.clock_gettime(process_time.clock_id) except OSError: - process_time.use_process_cputime = False + process_time.clock_id = None if process_time.use_getrusage: try: usage = resource.getrusage(resource.RUSAGE_SELF) @@ -256,9 +256,14 @@ except OSError: process_time.use_getrusage = False return _time.clock() - process_time.use_process_cputime = ( - hasattr(time, 'clock_gettime') - and hasattr(time, 'CLOCK_PROCESS_CPUTIME_ID')) + if (hasattr(time, 'clock_gettime') + and hasattr(time, 'CLOCK_PROF')): + process_time.clock_id = time.CLOCK_PROF + elif (hasattr(time, 'clock_gettime') + and hasattr(time, 'CLOCK_PROCESS_CPUTIME_ID')): + process_time.clock_id = time.CLOCK_PROCESS_CPUTIME_ID + else: + process_time.clock_id = None process_time.use_getrusage = has_resource process_time.use_times = hasattr(_time, 'times') if process_time.use_times: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 01:43:30 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 01:43:30 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_time=2Emonotoni?= =?utf8?q?c=28=29_pseudo-code_for_Mac?= Message-ID: http://hg.python.org/peps/rev/081d9add6f3a changeset: 4264:081d9add6f3a user: Victor Stinner date: Wed Apr 18 01:43:26 2012 +0200 summary: PEP 418: Fix time.monotonic() pseudo-code for Mac Use sys.platform, not os.name files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -148,7 +148,7 @@ monotonic.last = 0 monotonic.delta = 0 - elif os.name == 'mac': + elif sys.platform == 'darwin': def monotonic(): if monotonic.factor is None: factor = _time.mach_timebase_info() -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 01:54:29 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 01:54:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_mangle_keyword-?= =?utf8?q?only_argname_when_loading_defaults_=28closes_=2314607=29?= Message-ID: http://hg.python.org/cpython/rev/f8540b8d076c changeset: 76382:f8540b8d076c branch: 3.2 parent: 76377:428bece48029 user: Benjamin Peterson date: Tue Apr 17 19:53:21 2012 -0400 summary: mangle keyword-only argname when loading defaults (closes #14607) files: Lib/test/test_keywordonlyarg.py | 6 ++++++ Misc/NEWS | 2 ++ Python/compile.c | 6 +++++- 3 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_keywordonlyarg.py b/Lib/test/test_keywordonlyarg.py --- a/Lib/test/test_keywordonlyarg.py +++ b/Lib/test/test_keywordonlyarg.py @@ -170,6 +170,12 @@ # used to fail with a SystemError. lambda *, k1=unittest: None + def test_mangling(self): + class X: + def f(self, *, __a=42): + return __a + self.assertEqual(X().f(), 42) + def test_main(): run_unittest(KeywordOnlyArgTestCase) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #14607: Fix defaults keyword-only arguments which started with ``__``. + - Issue #13889: Check and (if necessary) set FPU control word before calling any of the dtoa.c string <-> float conversion functions, on MSVC builds of Python. This fixes issues when embedding Python in a Delphi app. diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1319,7 +1319,11 @@ arg_ty arg = asdl_seq_GET(kwonlyargs, i); expr_ty default_ = asdl_seq_GET(kw_defaults, i); if (default_) { - ADDOP_O(c, LOAD_CONST, arg->arg, consts); + PyObject *mangled = _Py_Mangle(c->u->u_private, arg->arg); + if (!mangled) + return -1; + ADDOP_O(c, LOAD_CONST, mangled, consts); + Py_DECREF(mangled); if (!compiler_visit_expr(c, default_)) { return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 01:54:40 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 01:54:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?b?OiBtZXJnZSAzLjIgKCMxNDYwNyk=?= Message-ID: http://hg.python.org/cpython/rev/22844ddce57b changeset: 76383:22844ddce57b parent: 76381:66bd85bcf916 parent: 76382:f8540b8d076c user: Benjamin Peterson date: Tue Apr 17 19:54:35 2012 -0400 summary: merge 3.2 (#14607) files: Lib/test/test_keywordonlyarg.py | 6 ++++++ Misc/NEWS | 2 ++ Python/compile.c | 6 +++++- 3 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_keywordonlyarg.py b/Lib/test/test_keywordonlyarg.py --- a/Lib/test/test_keywordonlyarg.py +++ b/Lib/test/test_keywordonlyarg.py @@ -170,6 +170,12 @@ # used to fail with a SystemError. lambda *, k1=unittest: None + def test_mangling(self): + class X: + def f(self, *, __a=42): + return __a + self.assertEqual(X().f(), 42) + def test_main(): run_unittest(KeywordOnlyArgTestCase) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ - Issue #14592: Attempting a relative import w/o __package__ or __name__ set in globals raises a KeyError. +- Issue #14607: Fix defaults keyword-only arguments which started with ``__``. + - Issue #10854: The ImportError raised when an extension module on Windows fails to import now uses the new path and name attributes from Issue #1559549. diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1409,7 +1409,11 @@ arg_ty arg = asdl_seq_GET(kwonlyargs, i); expr_ty default_ = asdl_seq_GET(kw_defaults, i); if (default_) { - ADDOP_O(c, LOAD_CONST, arg->arg, consts); + PyObject *mangled = _Py_Mangle(c->u->u_private, arg->arg); + if (!mangled) + return -1; + ADDOP_O(c, LOAD_CONST, mangled, consts); + Py_DECREF(mangled); if (!compiler_visit_expr(c, default_)) { return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 01:55:25 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 01:55:25 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_pseudo-code_of_?= =?utf8?q?time=2Emonotonic=28=29_on_Mac_OS_X?= Message-ID: http://hg.python.org/peps/rev/d1b6aa9e5873 changeset: 4265:d1b6aa9e5873 user: Victor Stinner date: Wed Apr 18 01:55:21 2012 +0200 summary: PEP 418: Fix pseudo-code of time.monotonic() on Mac OS X files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -152,7 +152,7 @@ def monotonic(): if monotonic.factor is None: factor = _time.mach_timebase_info() - monotonic.factor = timebase[0] / timebase[1] + monotonic.factor = timebase[0] / timebase[1] * 1e-9 return _time.mach_absolute_time() * monotonic.factor monotonic.factor = None -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 02:55:52 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 02:55:52 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_a_link_to_the_T?= =?utf8?q?wisted_monotonic_clock_issue?= Message-ID: http://hg.python.org/peps/rev/9f25c7e65744 changeset: 4266:9f25c7e65744 user: Victor Stinner date: Wed Apr 18 02:55:50 2012 +0200 summary: PEP 418: Add a link to the Twisted monotonic clock issue Reformat also "System Standby" section files: pep-0418.txt | 19 +++++++++++-------- 1 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1429,16 +1429,17 @@ System Standby ============== -The ACPI power state "S3" is as system standby mode, also called "Suspend to -RAM". RAM remains powered. +The ACPI power state "S3" is as system standby mode, also called +"Suspend to RAM". RAM remains powered. -On Windows, the WM_POWERBROADCAST message is send to Windows application -to notify them of power-management events (ex: ower status has changed). +On Windows, the ``WM_POWERBROADCAST`` message is send to Windows +application to notify them of power-management events (ex: ower status +has changed). -For Mac OS X, read `Registering and unregistering for sleep -and wake notifications -`_ (Technical -Q&A QA1340). +For Mac OS X, read `Registering and unregistering for sleep and wake +notifications +`_ +(Technical Q&A QA1340). Footnotes @@ -1517,6 +1518,8 @@ Time: +* `Twisted issue #2424: Add reactor option to start with monotonic clock + `_ * `gettimeofday() should never be used to measure time `_ by Thomas Habets (2010-09-05) * `hrtimers - subsystem for high-resolution kernel timers -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 03:42:15 2012 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2012 03:42:15 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2312599=3A_Be_more_s?= =?utf8?q?trict_in_accepting_None_vs=2E_a_false-like_object?= Message-ID: http://hg.python.org/cpython/rev/c1399cf7bd6a changeset: 76384:c1399cf7bd6a parent: 76381:66bd85bcf916 user: Brett Cannon date: Tue Apr 17 21:41:35 2012 -0400 summary: Issue #12599: Be more strict in accepting None vs. a false-like object in importlib. Thanks to PJE for pointing out the issue and Nick Coghlan for filing the bug. files: Lib/importlib/_bootstrap.py | 6 ++-- Lib/importlib/test/import_/test_path.py | 9 ++++++ Lib/importlib/test/test_util.py | 16 +++++++++++- Misc/NEWS | 4 +++ Python/importlib.h | Bin 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -217,7 +217,7 @@ """ def module_for_loader_wrapper(self, fullname, *args, **kwargs): module = sys.modules.get(fullname) - is_reload = bool(module) + is_reload = module is not None if not is_reload: # This must be done before open() is called as the 'io' module # implicitly imports 'locale' and would otherwise trigger an @@ -711,7 +711,7 @@ If 'hooks' is false then use sys.path_hooks. """ - if not hooks: + if hooks is None: hooks = sys.path_hooks for hook in hooks: try: @@ -753,7 +753,7 @@ def find_module(cls, fullname, path=None): """Find the module on sys.path or 'path' based on sys.path_hooks and sys.path_importer_cache.""" - if not path: + if path is None: path = sys.path for entry in path: try: diff --git a/Lib/importlib/test/import_/test_path.py b/Lib/importlib/test/import_/test_path.py --- a/Lib/importlib/test/import_/test_path.py +++ b/Lib/importlib/test/import_/test_path.py @@ -42,6 +42,15 @@ loader = machinery.PathFinder.find_module(module, [path]) self.assertTrue(loader is importer) + def test_empty_list(self): + # An empty list should not count as asking for sys.path. + module = 'module' + path = '' + importer = util.mock_modules(module) + with util.import_state(path_importer_cache={path: importer}, + path=[path]): + self.assertIsNone(machinery.PathFinder.find_module('module', [])) + def test_path_hooks(self): # Test that sys.path_hooks is used. # Test that sys.path_importer_cache is set. diff --git a/Lib/importlib/test/test_util.py b/Lib/importlib/test/test_util.py --- a/Lib/importlib/test/test_util.py +++ b/Lib/importlib/test/test_util.py @@ -65,9 +65,23 @@ self.assertEqual(wrapped.__name__, fxn.__name__) self.assertEqual(wrapped.__qualname__, fxn.__qualname__) + def test_false_module(self): + # If for some odd reason a module is considered false, still return it + # from sys.modules. + class FalseModule(types.ModuleType): + def __bool__(self): return False + + name = 'mod' + module = FalseModule(name) + with test_util.uncache(name): + self.assertFalse(module) + sys.modules[name] = module + given = self.return_module(name) + self.assertTrue(given is module) + + class SetPackageTests(unittest.TestCase): - """Tests for importlib.util.set_package.""" def verify(self, module, expect): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #12599: Be more strict in accepting None compared to a false-like + object for importlib.util.module_for_loader and + importlib.machinery.PathFinder. + - Issue #14592: Attempting a relative import w/o __package__ or __name__ set in globals raises a KeyError. diff --git a/Python/importlib.h b/Python/importlib.h index 3a03c462530658669296e8e99237c26924ff24b7..392b941b6deaf2be794da994178e0af499f1ba81 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 03:42:16 2012 From: python-checkins at python.org (brett.cannon) Date: Wed, 18 Apr 2012 03:42:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_Merge?= Message-ID: http://hg.python.org/cpython/rev/6762b943ee59 changeset: 76385:6762b943ee59 parent: 76384:c1399cf7bd6a parent: 76383:22844ddce57b user: Brett Cannon date: Tue Apr 17 21:42:07 2012 -0400 summary: Merge files: Lib/test/test_keywordonlyarg.py | 6 ++++++ Misc/NEWS | 2 ++ Python/compile.c | 6 +++++- 3 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_keywordonlyarg.py b/Lib/test/test_keywordonlyarg.py --- a/Lib/test/test_keywordonlyarg.py +++ b/Lib/test/test_keywordonlyarg.py @@ -170,6 +170,12 @@ # used to fail with a SystemError. lambda *, k1=unittest: None + def test_mangling(self): + class X: + def f(self, *, __a=42): + return __a + self.assertEqual(X().f(), 42) + def test_main(): run_unittest(KeywordOnlyArgTestCase) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,8 @@ - Issue #14592: Attempting a relative import w/o __package__ or __name__ set in globals raises a KeyError. +- Issue #14607: Fix defaults keyword-only arguments which started with ``__``. + - Issue #10854: The ImportError raised when an extension module on Windows fails to import now uses the new path and name attributes from Issue #1559549. diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1409,7 +1409,11 @@ arg_ty arg = asdl_seq_GET(kwonlyargs, i); expr_ty default_ = asdl_seq_GET(kw_defaults, i); if (default_) { - ADDOP_O(c, LOAD_CONST, arg->arg, consts); + PyObject *mangled = _Py_Mangle(c->u->u_private, arg->arg); + if (!mangled) + return -1; + ADDOP_O(c, LOAD_CONST, mangled, consts); + Py_DECREF(mangled); if (!compiler_visit_expr(c, default_)) { return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 04:48:13 2012 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 18 Apr 2012 04:48:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Clarify_that_a_?= =?utf8?q?new_connection_needs_to_be_made_after_the_close=2E?= Message-ID: http://hg.python.org/cpython/rev/f45605e5c037 changeset: 76386:f45605e5c037 branch: 2.7 parent: 76376:8a4c9a168d09 user: Raymond Hettinger date: Tue Apr 17 15:03:20 2012 -0400 summary: Clarify that a new connection needs to be made after the close. files: Doc/library/sqlite3.rst | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -51,6 +51,12 @@ shouldn't assemble your query using Python's string operations because doing so is insecure; it makes your program vulnerable to an SQL injection attack. +The data you've saved is persistent and is available in subsequent sessions:: + + import sqlite3 + conn = sqlite3.connect('/tmp/example') + c = conn.cursor() + Instead, use the DB-API's parameter substitution. Put ``?`` as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor's :meth:`~Cursor.execute` method. (Other database -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 04:48:14 2012 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 18 Apr 2012 04:48:14 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Clean-up_the_SQ?= =?utf8?q?Lite_introduction=2E?= Message-ID: http://hg.python.org/cpython/rev/d229032dc213 changeset: 76387:d229032dc213 branch: 2.7 user: Raymond Hettinger date: Tue Apr 17 22:48:06 2012 -0400 summary: Clean-up the SQLite introduction. files: Doc/library/sqlite3.rst | 52 ++++++++++++++-------------- 1 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -23,7 +23,7 @@ :file:`/tmp/example` file:: import sqlite3 - conn = sqlite3.connect('/tmp/example') + conn = sqlite3.connect('example.db') You can also supply the special name ``:memory:`` to create a database in RAM. @@ -33,13 +33,11 @@ c = conn.cursor() # Create table - c.execute('''create table stocks - (date text, trans text, symbol text, - qty real, price real)''') + c.execute('''CREATE TABLE stocks + (date text, trans text, symbol text, qty real, price real)''') # Insert a row of data - c.execute("""insert into stocks - values ('2006-01-05','BUY','RHAT',100,35.14)""") + c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)") # Save (commit) the changes conn.commit() @@ -47,16 +45,17 @@ # We can also close the cursor if we are done with it c.close() -Usually your SQL operations will need to use values from Python variables. You -shouldn't assemble your query using Python's string operations because doing so -is insecure; it makes your program vulnerable to an SQL injection attack. - The data you've saved is persistent and is available in subsequent sessions:: import sqlite3 - conn = sqlite3.connect('/tmp/example') + conn = sqlite3.connect('example.db') c = conn.cursor() +Usually your SQL operations will need to use values from Python variables. You +shouldn't assemble your query using Python's string operations because doing so +is insecure; it makes your program vulnerable to an SQL injection attack +(see http://xkcd.com/327/ for humorous example of what can go wrong). + Instead, use the DB-API's parameter substitution. Put ``?`` as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor's :meth:`~Cursor.execute` method. (Other database @@ -64,19 +63,20 @@ example:: # Never do this -- insecure! - symbol = 'IBM' - c.execute("select * from stocks where symbol = '%s'" % symbol) + symbol = 'RHAT' + c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) # Do this instead t = (symbol,) - c.execute('select * from stocks where symbol=?', t) + c.execute('SELECT * FROM stocks WHERE symbol=?', t) + print c.fetchone() - # Larger example - for t in [('2006-03-28', 'BUY', 'IBM', 1000, 45.00), - ('2006-04-05', 'BUY', 'MSFT', 1000, 72.00), - ('2006-04-06', 'SELL', 'IBM', 500, 53.00), - ]: - c.execute('insert into stocks values (?,?,?,?,?)', t) + # Larger example that inserts many records at a time + purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00), + ('2006-04-05', 'BUY', 'MSFT', 1000, 72.00), + ('2006-04-06', 'SELL', 'IBM', 500, 53.00), + ] + c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases) To retrieve data after executing a SELECT statement, you can either treat the cursor as an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to @@ -85,16 +85,13 @@ This example uses the iterator form:: - >>> c = conn.cursor() - >>> c.execute('select * from stocks order by price') - >>> for row in c: - ... print row - ... + >>> for row in c.execute('SELECT * FROM stocks ORDER BY price'): + print row + (u'2006-01-05', u'BUY', u'RHAT', 100, 35.14) (u'2006-03-28', u'BUY', u'IBM', 1000, 45.0) (u'2006-04-06', u'SELL', u'IBM', 500, 53.0) (u'2006-04-05', u'BUY', u'MSFT', 1000, 72.0) - >>> .. seealso:: @@ -107,6 +104,9 @@ The SQLite web page; the documentation describes the syntax and the available data types for the supported SQL dialect. + http://www.w3schools.com/sql/ + Tutorial, reference and examples for learning SQL syntax. + :pep:`249` - Database API Specification 2.0 PEP written by Marc-Andr? Lemburg. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Wed Apr 18 05:34:47 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 18 Apr 2012 05:34:47 +0200 Subject: [Python-checkins] Daily reference leaks (22844ddce57b): sum=0 Message-ID: results for 22844ddce57b on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogKG7BeA', '-x'] From ncoghlan at gmail.com Wed Apr 18 13:19:03 2012 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 18 Apr 2012 21:19:03 +1000 Subject: [Python-checkins] cpython: Fix #14600. Correct reference handling and naming of ImportError convenience In-Reply-To: References: Message-ID: On Wed, Apr 18, 2012 at 7:57 AM, brian.curtin wrote: > diff --git a/Python/errors.c b/Python/errors.c > --- a/Python/errors.c > +++ b/Python/errors.c > @@ -586,50 +586,43 @@ > ?#endif /* MS_WINDOWS */ > > ?PyObject * > -PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs) > +PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) > ?{ > - ? ?PyObject *val; > + ? ?PyObject *args, *kwargs, *error; > + > + ? ?args = PyTuple_New(1); > + ? ?if (args == NULL) > + ? ? ? ?return NULL; > + > + ? ?kwargs = PyDict_New(); > + ? ?if (args == NULL) > + ? ? ? ?return NULL; > + > + ? ?if (name == NULL) > + ? ? ? ?name = Py_None; > + > + ? ?if (path == NULL) > + ? ? ? ?path = Py_None; Py_INCREF's? Regards, Nick. -- Nick Coghlan?? |?? ncoghlan at gmail.com?? |?? Brisbane, Australia From python-checkins at python.org Wed Apr 18 13:20:43 2012 From: python-checkins at python.org (martin.v.loewis) Date: Wed, 18 Apr 2012 13:20:43 +0200 (CEST) Subject: [Python-checkins] r88948 - in tracker/instances/python-dev/html: user.index.html user.item.html user.openid.html user.register.html Message-ID: <3VXgqb1HfFzMMF@mail.python.org> Author: martin.v.loewis Date: Wed Apr 18 13:20:42 2012 New Revision: 88948 Log: Issue #342: Remove phone number from UI. Modified: tracker/instances/python-dev/html/user.index.html tracker/instances/python-dev/html/user.item.html tracker/instances/python-dev/html/user.openid.html tracker/instances/python-dev/html/user.register.html Modified: tracker/instances/python-dev/html/user.index.html ============================================================================== --- tracker/instances/python-dev/html/user.index.html (original) +++ tracker/instances/python-dev/html/user.index.html Wed Apr 18 13:20:42 2012 @@ -49,7 +49,6 @@ Real name Organisation Email address - Phone number Retire @@ -61,7 +60,6 @@       -  

Modified: tracker/instances/python-dev/html/user.item.html ============================================================================== --- tracker/instances/python-dev/html/user.item.html (original) +++ tracker/instances/python-dev/html/user.item.html Wed Apr 18 13:20:42 2012 @@ -90,11 +90,6 @@ - - Phone - - - Organisation Modified: tracker/instances/python-dev/html/user.openid.html ============================================================================== --- tracker/instances/python-dev/html/user.openid.html (original) +++ tracker/instances/python-dev/html/user.openid.html Wed Apr 18 13:20:42 2012 @@ -41,10 +41,6 @@ - Phone - phone - - Organisation organisation Modified: tracker/instances/python-dev/html/user.register.html ============================================================================== --- tracker/instances/python-dev/html/user.register.html (original) +++ tracker/instances/python-dev/html/user.register.html Wed Apr 18 13:20:42 2012 @@ -45,10 +45,6 @@ - Phone - phone - - Organisation organisation From python-checkins at python.org Wed Apr 18 15:31:10 2012 From: python-checkins at python.org (brian.curtin) Date: Wed, 18 Apr 2012 15:31:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_email_post-commit_revie?= =?utf8?q?w_comments=2E?= Message-ID: http://hg.python.org/cpython/rev/bf23a6c215f6 changeset: 76388:bf23a6c215f6 parent: 76385:6762b943ee59 user: Brian Curtin date: Wed Apr 18 08:30:51 2012 -0500 summary: Fix email post-commit review comments. Add INCREFs, fix args->kwargs, and a second args==NULL check was removed, left over from a merger with another function. Instead, checking msg==NULL does what that used to do in a roundabout way. files: Python/errors.c | 19 +++++++++++-------- 1 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -590,29 +590,32 @@ { PyObject *args, *kwargs, *error; + if (msg == NULL) + return NULL; + args = PyTuple_New(1); if (args == NULL) return NULL; kwargs = PyDict_New(); - if (args == NULL) + if (kwargs == NULL) return NULL; - if (name == NULL) + if (name == NULL) { + Py_INCREF(Py_None); name = Py_None; + } - if (path == NULL) + if (path == NULL) { + Py_INCREF(Py_None); path = Py_None; + } Py_INCREF(msg); - PyTuple_SetItem(args, 0, msg); + PyTuple_SetItem(args, 0, NULL);//msg); PyDict_SetItemString(kwargs, "name", name); PyDict_SetItemString(kwargs, "path", path); - /* args must at least be an empty tuple */ - if (args == NULL) - args = PyTuple_New(0); - error = PyObject_Call(PyExc_ImportError, args, kwargs); if (error!= NULL) { PyErr_SetObject((PyObject *) Py_TYPE(error), error); -- Repository URL: http://hg.python.org/cpython From ncoghlan at gmail.com Wed Apr 18 15:39:34 2012 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 18 Apr 2012 23:39:34 +1000 Subject: [Python-checkins] cpython: Fix email post-commit review comments. In-Reply-To: References: Message-ID: On Wed, Apr 18, 2012 at 11:31 PM, brian.curtin wrote: > - ? ?if (name == NULL) > + ? ?if (name == NULL) { > + ? ? ? ?Py_INCREF(Py_None); > ? ? ? ? name = Py_None; > + ? ?} A slightly more traditional way to write that would be: name = Py_None; Py_INCREF(name); > - ? ?if (path == NULL) > + ? ?if (path == NULL) { > + ? ? ? ?Py_INCREF(Py_None); > ? ? ? ? path = Py_None; > + ? ?} Ditto. > > ? ? Py_INCREF(msg); > - ? ?PyTuple_SetItem(args, 0, msg); > + ? ?PyTuple_SetItem(args, 0, NULL);//msg); However, *this* looks a lot more suspicious... accidental commit of debugging code? (if not for spotting this last problem, I wouldn't have even mentioned the first two) Cheers, Nick. -- Nick Coghlan?? |?? ncoghlan at gmail.com?? |?? Brisbane, Australia From rdmurray at bitdance.com Wed Apr 18 16:08:10 2012 From: rdmurray at bitdance.com (R. David Murray) Date: Wed, 18 Apr 2012 10:08:10 -0400 Subject: [Python-checkins] [Python-Dev] cpython: Fix email post-commit review comments. In-Reply-To: References: Message-ID: <20120418140811.2B8F62509E4@webabinitio.net> We're seeing segfuilts on the buildbots now. Example: http://www.python.org/dev/buildbot/all/builders/x86%20Ubuntu%20Shared%203.x/builds/5715 On Wed, 18 Apr 2012 23:39:34 +1000, Nick Coghlan wrote: > On Wed, Apr 18, 2012 at 11:31 PM, brian.curtin > wrote: > > - ?? ??if (name == NULL) > > + ?? ??if (name == NULL) { > > + ?? ?? ?? ??Py_INCREF(Py_None); > > ?? ?? ?? ?? name = Py_None; > > + ?? ??} > > A slightly more traditional way to write that would be: > > name = Py_None; > Py_INCREF(name); > > > - ?? ??if (path == NULL) > > + ?? ??if (path == NULL) { > > + ?? ?? ?? ??Py_INCREF(Py_None); > > ?? ?? ?? ?? path = Py_None; > > + ?? ??} > > Ditto. > > > > > ?? ?? Py_INCREF(msg); > > - ?? ??PyTuple_SetItem(args, 0, msg); > > + ?? ??PyTuple_SetItem(args, 0, NULL);//msg); > > However, *this* looks a lot more suspicious... accidental commit of > debugging code? > > (if not for spotting this last problem, I wouldn't have even mentioned > the first two) > > Cheers, > Nick. > > -- > Nick Coghlan???? |???? ncoghlan at gmail.com???? |???? Brisbane, Australia > _______________________________________________ > Python-Dev mailing list > Python-Dev at python.org > http://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: http://mail.python.org/mailman/options/python-dev/rdmurray%40bitdance.com From python-checkins at python.org Wed Apr 18 16:48:07 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 16:48:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_fix_refcnt/style/debuging_o?= =?utf8?q?versights?= Message-ID: http://hg.python.org/cpython/rev/e8c87226bcb3 changeset: 76389:e8c87226bcb3 user: Benjamin Peterson date: Wed Apr 18 10:48:00 2012 -0400 summary: fix refcnt/style/debuging oversights files: Python/errors.c | 12 +++++++----- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -593,13 +593,15 @@ if (msg == NULL) return NULL; - args = PyTuple_New(1); + args = PyTuple_New(0); if (args == NULL) return NULL; kwargs = PyDict_New(); - if (kwargs == NULL) + if (kwargs == NULL) { + Py_DECREF(args); return NULL; + } if (name == NULL) { Py_INCREF(Py_None); @@ -612,13 +614,13 @@ } Py_INCREF(msg); - PyTuple_SetItem(args, 0, NULL);//msg); + PyTuple_SET_ITEM(args, 0, msg); PyDict_SetItemString(kwargs, "name", name); PyDict_SetItemString(kwargs, "path", path); error = PyObject_Call(PyExc_ImportError, args, kwargs); - if (error!= NULL) { - PyErr_SetObject((PyObject *) Py_TYPE(error), error); + if (error != NULL) { + PyErr_SetObject((PyObject *)Py_TYPE(error), error); Py_DECREF(error); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 16:55:51 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 16:55:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_rollback_005fd1fe31ab_=28se?= =?utf8?q?e_=2314609_and_=2314582=29?= Message-ID: http://hg.python.org/cpython/rev/db5e3431ee4c changeset: 76390:db5e3431ee4c user: Benjamin Peterson date: Wed Apr 18 10:55:43 2012 -0400 summary: rollback 005fd1fe31ab (see #14609 and #14582) Being able to overload a sys.module entry during import of a module was broken by this changeset. files: Lib/importlib/_bootstrap.py | 16 +--- Lib/importlib/test/import_/test_caching.py | 32 ++++++++- Misc/NEWS | 3 - Python/import.c | 19 +---- Python/importlib.h | Bin 5 files changed, 40 insertions(+), 30 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -984,12 +984,12 @@ loader = _find_module(name, path) if loader is None: raise ImportError(_ERR_MSG.format(name), name=name) - elif name in sys.modules: - # The parent module already imported this module. - module = sys.modules[name] - else: - module = loader.load_module(name) + elif name not in sys.modules: + # The parent import may have already imported this module. + loader.load_module(name) verbose_message('import {!r} # {!r}', name, loader) + # Backwards-compatibility; be nicer to skip the dict lookup. + module = sys.modules[name] if parent: # Set the module as an attribute on its parent. parent_module = sys.modules[parent] @@ -1088,11 +1088,7 @@ # Return up to the first dot in 'name'. This is complicated by the fact # that 'name' may be relative. if level == 0: - index = name.find('.') - if index == -1: - return module - else: - return sys.modules[name[:index]] + return sys.modules[name.partition('.')[0]] elif not name: return module else: diff --git a/Lib/importlib/test/import_/test_caching.py b/Lib/importlib/test/import_/test_caching.py --- a/Lib/importlib/test/import_/test_caching.py +++ b/Lib/importlib/test/import_/test_caching.py @@ -47,12 +47,36 @@ mock.load_module = MethodType(load_module, mock) return mock - def test_using_loader_return(self): - loader_return = 'hi there!' - with self.create_mock('module', return_=loader_return) as mock: + # __import__ inconsistent between loaders and built-in import when it comes + # to when to use the module in sys.modules and when not to. + @import_util.importlib_only + def test_using_cache_after_loader(self): + # [from cache on return] + with self.create_mock('module') as mock: with util.import_state(meta_path=[mock]): module = import_util.import_('module') - self.assertEqual(module, loader_return) + self.assertEqual(id(module), id(sys.modules['module'])) + + # See test_using_cache_after_loader() for reasoning. + @import_util.importlib_only + def test_using_cache_for_assigning_to_attribute(self): + # [from cache to attribute] + with self.create_mock('pkg.__init__', 'pkg.module') as importer: + with util.import_state(meta_path=[importer]): + module = import_util.import_('pkg.module') + self.assertTrue(hasattr(module, 'module')) + self.assertTrue(id(module.module), id(sys.modules['pkg.module'])) + + # See test_using_cache_after_loader() for reasoning. + @import_util.importlib_only + def test_using_cache_for_fromlist(self): + # [from cache for fromlist] + with self.create_mock('pkg.__init__', 'pkg.module') as importer: + with util.import_state(meta_path=[importer]): + module = import_util.import_('pkg', fromlist=['module']) + self.assertTrue(hasattr(module, 'module')) + self.assertEqual(id(module.module), + id(sys.modules['pkg.module'])) def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,9 +23,6 @@ fails to import now uses the new path and name attributes from Issue #1559549. -- Issue #14582: Import directly returns the module as returned by a loader when - possible instead of fetching it from sys.modules. - - Issue #13889: Check and (if necessary) set FPU control word before calling any of the dtoa.c string <-> float conversion functions, on MSVC builds of Python. This fixes issues when embedding Python in a Delphi app. diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2447,22 +2447,15 @@ Py_DECREF(partition); if (level == 0) { - if (PyUnicode_GET_LENGTH(name) == - PyUnicode_GET_LENGTH(front)) { - final_mod = mod; + final_mod = PyDict_GetItem(interp->modules, front); + Py_DECREF(front); + if (final_mod == NULL) { + PyErr_Format(PyExc_KeyError, + "%R not in sys.modules as expected", front); } else { - final_mod = PyDict_GetItem(interp->modules, front); - if (final_mod == NULL) { - PyErr_Format(PyExc_KeyError, - "%R not in sys.modules as expected", front); - } + Py_INCREF(final_mod); } - Py_DECREF(front); - if (final_mod == NULL) { - goto error_with_unlock; - } - Py_INCREF(final_mod); } else { Py_ssize_t cut_off = PyUnicode_GET_LENGTH(name) - diff --git a/Python/importlib.h b/Python/importlib.h index 392b941b6deaf2be794da994178e0af499f1ba81..6279e00d5b1b2f405e6ff99b2234bf05321b10d7 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 17:01:04 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 18 Apr 2012 17:01:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_it_for_good_=3A-=29?= Message-ID: http://hg.python.org/cpython/rev/cb6811eb20ef changeset: 76391:cb6811eb20ef parent: 76389:e8c87226bcb3 user: Antoine Pitrou date: Wed Apr 18 16:57:54 2012 +0200 summary: Fix it for good :-) files: Python/errors.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -593,7 +593,7 @@ if (msg == NULL) return NULL; - args = PyTuple_New(0); + args = PyTuple_New(1); if (args == NULL) return NULL; @@ -604,12 +604,10 @@ } if (name == NULL) { - Py_INCREF(Py_None); name = Py_None; } if (path == NULL) { - Py_INCREF(Py_None); path = Py_None; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 17:01:05 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 18 Apr 2012 17:01:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_Merge_heads?= Message-ID: http://hg.python.org/cpython/rev/4111a2b5ff57 changeset: 76392:4111a2b5ff57 parent: 76391:cb6811eb20ef parent: 76390:db5e3431ee4c user: Antoine Pitrou date: Wed Apr 18 16:59:52 2012 +0200 summary: Merge heads files: Lib/importlib/_bootstrap.py | 16 +--- Lib/importlib/test/import_/test_caching.py | 32 ++++++++- Misc/NEWS | 3 - Python/import.c | 19 +---- Python/importlib.h | Bin 5 files changed, 40 insertions(+), 30 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -984,12 +984,12 @@ loader = _find_module(name, path) if loader is None: raise ImportError(_ERR_MSG.format(name), name=name) - elif name in sys.modules: - # The parent module already imported this module. - module = sys.modules[name] - else: - module = loader.load_module(name) + elif name not in sys.modules: + # The parent import may have already imported this module. + loader.load_module(name) verbose_message('import {!r} # {!r}', name, loader) + # Backwards-compatibility; be nicer to skip the dict lookup. + module = sys.modules[name] if parent: # Set the module as an attribute on its parent. parent_module = sys.modules[parent] @@ -1088,11 +1088,7 @@ # Return up to the first dot in 'name'. This is complicated by the fact # that 'name' may be relative. if level == 0: - index = name.find('.') - if index == -1: - return module - else: - return sys.modules[name[:index]] + return sys.modules[name.partition('.')[0]] elif not name: return module else: diff --git a/Lib/importlib/test/import_/test_caching.py b/Lib/importlib/test/import_/test_caching.py --- a/Lib/importlib/test/import_/test_caching.py +++ b/Lib/importlib/test/import_/test_caching.py @@ -47,12 +47,36 @@ mock.load_module = MethodType(load_module, mock) return mock - def test_using_loader_return(self): - loader_return = 'hi there!' - with self.create_mock('module', return_=loader_return) as mock: + # __import__ inconsistent between loaders and built-in import when it comes + # to when to use the module in sys.modules and when not to. + @import_util.importlib_only + def test_using_cache_after_loader(self): + # [from cache on return] + with self.create_mock('module') as mock: with util.import_state(meta_path=[mock]): module = import_util.import_('module') - self.assertEqual(module, loader_return) + self.assertEqual(id(module), id(sys.modules['module'])) + + # See test_using_cache_after_loader() for reasoning. + @import_util.importlib_only + def test_using_cache_for_assigning_to_attribute(self): + # [from cache to attribute] + with self.create_mock('pkg.__init__', 'pkg.module') as importer: + with util.import_state(meta_path=[importer]): + module = import_util.import_('pkg.module') + self.assertTrue(hasattr(module, 'module')) + self.assertTrue(id(module.module), id(sys.modules['pkg.module'])) + + # See test_using_cache_after_loader() for reasoning. + @import_util.importlib_only + def test_using_cache_for_fromlist(self): + # [from cache for fromlist] + with self.create_mock('pkg.__init__', 'pkg.module') as importer: + with util.import_state(meta_path=[importer]): + module = import_util.import_('pkg', fromlist=['module']) + self.assertTrue(hasattr(module, 'module')) + self.assertEqual(id(module.module), + id(sys.modules['pkg.module'])) def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,9 +23,6 @@ fails to import now uses the new path and name attributes from Issue #1559549. -- Issue #14582: Import directly returns the module as returned by a loader when - possible instead of fetching it from sys.modules. - - Issue #13889: Check and (if necessary) set FPU control word before calling any of the dtoa.c string <-> float conversion functions, on MSVC builds of Python. This fixes issues when embedding Python in a Delphi app. diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2447,22 +2447,15 @@ Py_DECREF(partition); if (level == 0) { - if (PyUnicode_GET_LENGTH(name) == - PyUnicode_GET_LENGTH(front)) { - final_mod = mod; + final_mod = PyDict_GetItem(interp->modules, front); + Py_DECREF(front); + if (final_mod == NULL) { + PyErr_Format(PyExc_KeyError, + "%R not in sys.modules as expected", front); } else { - final_mod = PyDict_GetItem(interp->modules, front); - if (final_mod == NULL) { - PyErr_Format(PyExc_KeyError, - "%R not in sys.modules as expected", front); - } + Py_INCREF(final_mod); } - Py_DECREF(front); - if (final_mod == NULL) { - goto error_with_unlock; - } - Py_INCREF(final_mod); } else { Py_ssize_t cut_off = PyUnicode_GET_LENGTH(name) - diff --git a/Python/importlib.h b/Python/importlib.h index 392b941b6deaf2be794da994178e0af499f1ba81..6279e00d5b1b2f405e6ff99b2234bf05321b10d7 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 17:24:40 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 17:24:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_SETUP=5FWITH_ac?= =?utf8?q?ts_like_SETUP=5FFINALLY_for_the_purposes_of_setting_f=5Flineno_?= =?utf8?q?=28closes?= Message-ID: http://hg.python.org/cpython/rev/6a0a073e8461 changeset: 76393:6a0a073e8461 branch: 3.2 parent: 76382:f8540b8d076c user: Benjamin Peterson date: Wed Apr 18 11:14:31 2012 -0400 summary: SETUP_WITH acts like SETUP_FINALLY for the purposes of setting f_lineno (closes #14612) files: Lib/test/test_sys_settrace.py | 11 +++++++++++ Misc/NEWS | 2 ++ Objects/frameobject.c | 6 ++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -671,6 +671,14 @@ no_jump_to_non_integers.jump = (2, "Spam") no_jump_to_non_integers.output = [True] +def jump_across_with(output): + with open(support.TESTFN, "wb") as fp: + pass + with open(support.TESTFN, "wb") as fp: + pass +jump_across_with.jump = (1, 3) +jump_across_with.output = [] + # This verifies that you can't set f_lineno via _getframe or similar # trickery. def no_jump_without_trace_function(): @@ -740,6 +748,9 @@ self.run_test(no_jump_to_non_integers) def test_19_no_jump_without_trace_function(self): no_jump_without_trace_function() + def test_jump_across_with(self): + self.addCleanup(support.unlink, support.TESTFN) + self.run_test(jump_across_with) def test_20_large_function(self): d = {} diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #14612: Fix jumping around with blocks by setting f_lineno. + - Issue #14607: Fix defaults keyword-only arguments which started with ``__``. - Issue #13889: Check and (if necessary) set FPU control word before calling diff --git a/Objects/frameobject.c b/Objects/frameobject.c --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -199,6 +199,7 @@ case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: blockstack[blockstack_top++] = addr; in_finally[blockstack_top-1] = 0; break; @@ -206,7 +207,7 @@ case POP_BLOCK: assert(blockstack_top > 0); setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { in_finally[blockstack_top-1] = 1; } else { @@ -221,7 +222,7 @@ * be seeing such an END_FINALLY.) */ if (blockstack_top > 0) { setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { blockstack_top--; } } @@ -283,6 +284,7 @@ case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: delta_iblock++; break; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 17:24:41 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 17:24:41 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?b?OiBtZXJnZSAzLjIgKCMxNDYxMik=?= Message-ID: http://hg.python.org/cpython/rev/0695f5d028a7 changeset: 76394:0695f5d028a7 parent: 76392:4111a2b5ff57 parent: 76393:6a0a073e8461 user: Benjamin Peterson date: Wed Apr 18 11:19:00 2012 -0400 summary: merge 3.2 (#14612) files: Lib/test/test_sys_settrace.py | 11 +++++++++++ Misc/NEWS | 2 ++ Objects/frameobject.c | 6 ++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -675,6 +675,14 @@ no_jump_to_non_integers.jump = (2, "Spam") no_jump_to_non_integers.output = [True] +def jump_across_with(output): + with open(support.TESTFN, "wb") as fp: + pass + with open(support.TESTFN, "wb") as fp: + pass +jump_across_with.jump = (1, 3) +jump_across_with.output = [] + # This verifies that you can't set f_lineno via _getframe or similar # trickery. def no_jump_without_trace_function(): @@ -750,6 +758,9 @@ # Must set sys.settrace(None) in setUp(), else condition is not # triggered. no_jump_without_trace_function() + def test_jump_across_with(self): + self.addCleanup(support.unlink, support.TESTFN) + self.run_test(jump_across_with) def test_20_large_function(self): d = {} diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -14,6 +14,8 @@ object for importlib.util.module_for_loader and importlib.machinery.PathFinder. +- Issue #14612: Fix jumping around with blocks by setting f_lineno. + - Issue #14592: Attempting a relative import w/o __package__ or __name__ set in globals raises a KeyError. diff --git a/Objects/frameobject.c b/Objects/frameobject.c --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -199,6 +199,7 @@ case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: blockstack[blockstack_top++] = addr; in_finally[blockstack_top-1] = 0; break; @@ -206,7 +207,7 @@ case POP_BLOCK: assert(blockstack_top > 0); setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { in_finally[blockstack_top-1] = 1; } else { @@ -221,7 +222,7 @@ * be seeing such an END_FINALLY.) */ if (blockstack_top > 0) { setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { blockstack_top--; } } @@ -283,6 +284,7 @@ case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: delta_iblock++; break; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 17:24:42 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 17:24:42 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_SETUP=5FWITH_ac?= =?utf8?q?ts_like_SETUP=5FFINALLY_for_the_purposes_of_setting_f=5Flineno_?= =?utf8?q?=28closes?= Message-ID: http://hg.python.org/cpython/rev/67be12ab8948 changeset: 76395:67be12ab8948 branch: 2.7 parent: 76387:d229032dc213 user: Benjamin Peterson date: Wed Apr 18 11:14:31 2012 -0400 summary: SETUP_WITH acts like SETUP_FINALLY for the purposes of setting f_lineno (closes #14612) files: Lib/test/test_sys_settrace.py | 11 +++++++++++ Misc/NEWS | 2 ++ Objects/frameobject.c | 6 ++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -670,6 +670,14 @@ no_jump_to_non_integers.jump = (2, "Spam") no_jump_to_non_integers.output = [True] +def jump_across_with(output): + with open(test_support.TESTFN, "wb") as fp: + pass + with open(test_support.TESTFN, "wb") as fp: + pass +jump_across_with.jump = (1, 3) +jump_across_with.output = [] + # This verifies that you can't set f_lineno via _getframe or similar # trickery. def no_jump_without_trace_function(): @@ -739,6 +747,9 @@ self.run_test(no_jump_to_non_integers) def test_19_no_jump_without_trace_function(self): no_jump_without_trace_function() + def test_jump_across_with(self): + self.addCleanup(test_support.unlink, test_support.TESTFN) + self.run_test(jump_across_with) def test_20_large_function(self): d = {} diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,8 @@ Core and Builtins ----------------- +- Issue #14612: Fix jumping around with blocks by setting f_lineno. + - Issue #13889: Check and (if necessary) set FPU control word before calling any of the dtoa.c string <-> float conversion functions, on MSVC builds of Python. This fixes issues when embedding Python in a Delphi app. diff --git a/Objects/frameobject.c b/Objects/frameobject.c --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -214,6 +214,7 @@ case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: blockstack[blockstack_top++] = addr; in_finally[blockstack_top-1] = 0; break; @@ -221,7 +222,7 @@ case POP_BLOCK: assert(blockstack_top > 0); setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { in_finally[blockstack_top-1] = 1; } else { @@ -236,7 +237,7 @@ * be seeing such an END_FINALLY.) */ if (blockstack_top > 0) { setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { blockstack_top--; } } @@ -298,6 +299,7 @@ case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: delta_iblock++; break; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 17:26:29 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 17:26:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_improve?= Message-ID: http://hg.python.org/cpython/rev/d368cc86dbc9 changeset: 76396:d368cc86dbc9 branch: 3.2 parent: 76393:6a0a073e8461 user: Benjamin Peterson date: Wed Apr 18 11:25:12 2012 -0400 summary: improve files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,7 +12,7 @@ - Issue #14612: Fix jumping around with blocks by setting f_lineno. -- Issue #14607: Fix defaults keyword-only arguments which started with ``__``. +- Issue #14607: Fix keyword-only arguments which started with ``__``. - Issue #13889: Check and (if necessary) set FPU control word before calling any of the dtoa.c string <-> float conversion functions, on MSVC builds of -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 17:26:30 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 17:26:30 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/220efaf42216 changeset: 76397:220efaf42216 parent: 76394:0695f5d028a7 parent: 76396:d368cc86dbc9 user: Benjamin Peterson date: Wed Apr 18 11:26:02 2012 -0400 summary: merge 3.2 files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,7 +19,7 @@ - Issue #14592: Attempting a relative import w/o __package__ or __name__ set in globals raises a KeyError. -- Issue #14607: Fix defaults keyword-only arguments which started with ``__``. +- Issue #14607: Fix keyword-only arguments which started with ``__``. - Issue #10854: The ImportError raised when an extension module on Windows fails to import now uses the new path and name attributes from -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 19:02:18 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 18 Apr 2012 19:02:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_The_previous_code_is_correc?= =?utf8?q?t=2C_but_hard_to_verify=3A_The_libmpdec_documentation?= Message-ID: http://hg.python.org/cpython/rev/7921a22b72f4 changeset: 76398:7921a22b72f4 user: Stefan Krah date: Wed Apr 18 17:48:34 2012 +0200 summary: The previous code is correct, but hard to verify: The libmpdec documentation rightfully states that an mpd_t with a coefficient flagged as MPD_CONST_DATA must not be in the position of the result operand. In this particular case several assumptions guarantee that a resize will never occur in all possible code paths, which was the reason for using MPD_CONST_DATA and saving an instruction by omitting the initialization of tmp.alloc. For readability, tmp is now flagged as MPD_STATIC_DATA and tmp.alloc is initialized. files: Modules/_decimal/libmpdec/mpdecimal.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -1280,7 +1280,8 @@ /* At this point a->digits+a->exp <= MPD_RDIGITS+1, * so the shift fits. */ tmp.data = tmp_data; - tmp.flags = MPD_STATIC|MPD_CONST_DATA; + tmp.flags = MPD_STATIC|MPD_STATIC_DATA; + tmp.alloc = 2; mpd_qsshiftr(&tmp, a, -a->exp); tmp.exp = 0; a = &tmp; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 19:02:18 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 18 Apr 2012 19:02:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Support_mythical_ones=27_co?= =?utf8?q?mplement_machines=2E?= Message-ID: http://hg.python.org/cpython/rev/251c1a854f2f changeset: 76399:251c1a854f2f user: Stefan Krah date: Wed Apr 18 17:57:56 2012 +0200 summary: Support mythical ones' complement machines. files: Modules/_decimal/libmpdec/mpdecimal.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -1340,7 +1340,7 @@ if (u <= MPD_SSIZE_MAX) { return isneg ? -((mpd_ssize_t)u) : (mpd_ssize_t)u; } - else if (isneg && u-1 == MPD_SSIZE_MAX) { + else if (isneg && u+(MPD_SSIZE_MIN+MPD_SSIZE_MAX) == MPD_SSIZE_MAX) { return MPD_SSIZE_MIN; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 19:02:20 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 18 Apr 2012 19:02:20 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_comments_and_whitespace?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/5a485cf7da8d changeset: 76400:5a485cf7da8d user: Stefan Krah date: Wed Apr 18 18:08:20 2012 +0200 summary: Fix comments and whitespace. files: Modules/_decimal/libmpdec/mpdecimal.c | 16 +++++++------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -2484,7 +2484,7 @@ } result->data[i++] = z; - /* scan the rest of y for digit > 1 */ + /* scan the rest of y for digits > 1 */ for (; k < MPD_RDIGITS; k++) { ybit = y % 10; y /= 10; @@ -2492,7 +2492,7 @@ goto invalid_operation; } } - /* scan the rest of big for digit > 1 */ + /* scan the rest of big for digits > 1 */ for (; i < big->len; i++) { y = big->data[i]; for (k = 0; k < MPD_RDIGITS; k++) { @@ -2571,7 +2571,7 @@ } for (i = 0; i < len; i++) { - x = (i < a->len) ? a->data[i] : 0; + x = (i < a->len) ? a->data[i] : 0; z = 0; for (k = 0; k < MPD_RDIGITS; k++) { xbit = x % 10; @@ -2674,7 +2674,7 @@ z += (xbit|ybit) ? mpd_pow10[k] : 0; } - /* scan and copy the rest of y for digit > 1 */ + /* scan for digits > 1 and copy the rest of y */ for (; k < MPD_RDIGITS; k++) { ybit = y % 10; y /= 10; @@ -2684,7 +2684,7 @@ z += ybit*mpd_pow10[k]; } result->data[i++] = z; - /* scan and copy the rest of big for digit > 1 */ + /* scan for digits > 1 and copy the rest of big */ for (; i < big->len; i++) { y = big->data[i]; for (k = 0; k < MPD_RDIGITS; k++) { @@ -2710,7 +2710,7 @@ } /* - * Rotate the coefficient of a by b->data digits. b must be an integer with + * Rotate the coefficient of 'a' by 'b' digits. 'b' must be an integer with * exponent 0. */ void @@ -2993,7 +2993,7 @@ z += (xbit^ybit) ? mpd_pow10[k] : 0; } - /* scan and copy the rest of y for digit > 1 */ + /* scan for digits > 1 and copy the rest of y */ for (; k < MPD_RDIGITS; k++) { ybit = y % 10; y /= 10; @@ -3003,7 +3003,7 @@ z += ybit*mpd_pow10[k]; } result->data[i++] = z; - /* scan and copy the rest of big for digit > 1 */ + /* scan for digits > 1 and copy the rest of big */ for (; i < big->len; i++) { y = big->data[i]; for (k = 0; k < MPD_RDIGITS; k++) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 19:02:21 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 18 Apr 2012 19:02:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Remove_redundant_finalizati?= =?utf8?q?on_of_the_result=2E?= Message-ID: http://hg.python.org/cpython/rev/90e986c72b5f changeset: 76401:90e986c72b5f user: Stefan Krah date: Wed Apr 18 18:25:37 2012 +0200 summary: Remove redundant finalization of the result. files: Modules/_decimal/libmpdec/mpdecimal.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -3054,8 +3054,6 @@ else { mpd_qplus(result, a, ctx, status); } - - mpd_qfinalize(result, ctx, status); } static inline void -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 19:02:23 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 18 Apr 2012 19:02:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Cosmetic_change=3A_initiali?= =?utf8?q?ze_digits_to_1_=28redundant=29=2E?= Message-ID: http://hg.python.org/cpython/rev/2433580ae8f3 changeset: 76402:2433580ae8f3 user: Stefan Krah date: Wed Apr 18 18:45:22 2012 +0200 summary: Cosmetic change: initialize digits to 1 (redundant). files: Modules/_decimal/libmpdec/mpdecimal.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -3089,7 +3089,7 @@ { mpd_t *big, *small; MPD_NEW_STATIC(big_aligned,0,0,0,0); - MPD_NEW_CONST(tiny,0,0,0,1,1,1); + MPD_NEW_CONST(tiny,0,0,1,1,1,1); mpd_uint_t carry; mpd_ssize_t newsize, shift; mpd_ssize_t exp, i; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 19:02:27 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 18 Apr 2012 19:02:27 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Explain_the_strategy_to_avo?= =?utf8?q?id_huge_alignment_shifts_in_=5Fmpd=5Fqadd=28=29_in_detail=2E?= Message-ID: http://hg.python.org/cpython/rev/a5c8bf5d1d5b changeset: 76403:a5c8bf5d1d5b user: Stefan Krah date: Wed Apr 18 18:59:56 2012 +0200 summary: Explain the strategy to avoid huge alignment shifts in _mpd_qadd() in detail. files: Modules/_decimal/libmpdec/mpdecimal.c | 41 ++++++++++++-- 1 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -3103,14 +3103,43 @@ _mpd_ptrswap(&big, &small); swap++; } + /* align the coefficients */ if (!mpd_iszerocoeff(big)) { - /* Test for adjexp(small) + big->digits < adjexp(big), if big-digits > prec - * Test for adjexp(small) + prec + 1 < adjexp(big), if big-digits <= prec - * If true, the magnitudes of the numbers are so far apart that one can as - * well add or subtract 1*10**big->exp. */ exp = big->exp - 1; exp += (big->digits > ctx->prec) ? 0 : big->digits-ctx->prec-1; if (mpd_adjexp(small) < exp) { + /* + * Avoid huge shifts by substituting a value for small that is + * guaranteed to produce the same results. + * + * adjexp(small) < exp if and only if: + * + * bdigits <= prec AND + * bdigits+shift >= prec+2+sdigits AND + * exp = bexp+bdigits-prec-2 + * + * 1234567000000000 -> bdigits + shift + * ----------XX1234 -> sdigits + * ----------X1 -> tiny-digits + * |- prec -| + * + * OR + * + * bdigits > prec AND + * shift > sdigits AND + * exp = bexp-1 + * + * 1234567892100000 -> bdigits + shift + * ----------XX1234 -> sdigits + * ----------X1 -> tiny-digits + * |- prec -| + * + * If tiny is zero, adding or subtracting is a no-op. + * Otherwise, adding tiny generates a non-zero digit either + * below the rounding digit or the least significant digit + * of big. When subtracting, tiny is in the same position as + * the carry that would be generated by subtracting sdigits. + */ mpd_copy_flags(&tiny, small); tiny.exp = exp; tiny.digits = 1; @@ -3118,7 +3147,7 @@ tiny.data[0] = mpd_iszerocoeff(small) ? 0 : 1; small = &tiny; } - /* this cannot wrap: the difference is positive and <= maxprec+1 */ + /* This cannot wrap: the difference is positive and <= maxprec */ shift = big->exp - small->exp; if (!mpd_qshiftl(&big_aligned, big, shift, status)) { mpd_seterror(result, MPD_Malloc_error, status); @@ -3521,7 +3550,7 @@ /* Internal function. */ static void _mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, - const mpd_context_t *ctx, uint32_t *status) + const mpd_context_t *ctx, uint32_t *status) { MPD_NEW_STATIC(aligned,0,0,0,0); mpd_ssize_t qsize, rsize; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 19:28:51 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 18 Apr 2012 19:28:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_1=29_Simplify_comment_--_on?= =?utf8?q?e_has_to_read_the_complete_proof_=28available_in_ACL2=29?= Message-ID: http://hg.python.org/cpython/rev/aa8a25c161a4 changeset: 76404:aa8a25c161a4 user: Stefan Krah date: Wed Apr 18 19:27:32 2012 +0200 summary: 1) Simplify comment -- one has to read the complete proof (available in ACL2) in order to understand the algorithm anyway. 2) v->exp == -v->digits may be assumed. 3) Fix comment (v always shares data with a). files: Modules/_decimal/libmpdec/mpdecimal.c | 15 +++++++-------- 1 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -6691,10 +6691,7 @@ return i-1; } -/* - * Initial approximation for the reciprocal. Result has MPD_RDIGITS-2 - * significant digits. - */ +/* Initial approximation for the reciprocal. */ static void _mpd_qreciprocal_approx(mpd_t *z, const mpd_t *v, uint32_t *status) { @@ -6702,6 +6699,8 @@ mpd_uint_t dummy, word; int n; + assert(v->exp == -v->digits); + _mpd_get_msdigits(&dummy, &word, v, MPD_RDIGITS); n = mpd_word_digits(word); word *= mpd_pow10[MPD_RDIGITS-n]; @@ -6710,7 +6709,7 @@ (void)_mpd_shortdiv(z->data, p10data, 2, word); mpd_clear_flags(z); - z->exp = -(v->exp + v->digits) - (MPD_RDIGITS-2); + z->exp = -(MPD_RDIGITS-2); z->len = (z->data[1] == 0) ? 1 : 2; mpd_setdigits(z); } @@ -6723,7 +6722,7 @@ mpd_context_t varcontext, maxcontext; mpd_t *z = result; /* current approximation */ mpd_t *v; /* a, normalized to a number between 0.1 and 1 */ - MPD_NEW_SHARED(vtmp, a); /* by default v will share data with a */ + MPD_NEW_SHARED(vtmp, a); /* v shares data with a */ MPD_NEW_STATIC(s,0,0,0,0); /* temporary variable */ MPD_NEW_STATIC(t,0,0,0,0); /* temporary variable */ MPD_NEW_CONST(two,0,0,1,1,1,2); /* const 2 */ @@ -6732,9 +6731,9 @@ uint8_t sign = mpd_sign(a); int i; + assert(result != a); + v = &vtmp; - assert(result != a); - mpd_clear_flags(v); adj = v->digits + v->exp; v->exp = -v->digits; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 20:52:22 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 18 Apr 2012 20:52:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2311750=3A_The_Windo?= =?utf8?q?ws_API_functions_scattered_in_the_=5Fsubprocess_and?= Message-ID: http://hg.python.org/cpython/rev/f3a27d11101a changeset: 76405:f3a27d11101a user: Antoine Pitrou date: Wed Apr 18 20:51:15 2012 +0200 summary: Issue #11750: The Windows API functions scattered in the _subprocess and _multiprocessing.win32 modules now live in a single module "_winapi". Patch by sbt. files: Lib/multiprocessing/connection.py | 124 +- Lib/multiprocessing/forking.py | 31 +- Lib/multiprocessing/heap.py | 6 +- Lib/multiprocessing/reduction.py | 6 +- Lib/subprocess.py | 106 +- Lib/test/test_multiprocessing.py | 2 +- Misc/NEWS | 4 + Modules/_multiprocessing/multiprocessing.c | 83 +- Modules/_multiprocessing/win32_functions.c | 823 ------ Modules/_winapi.c | 1326 ++++++++++ PC/_subprocess.c | 697 ----- PC/config.c | 6 +- PCbuild/_multiprocessing.vcproj | 4 - PCbuild/pythoncore.vcproj | 8 +- setup.py | 1 - 15 files changed, 1562 insertions(+), 1665 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -51,12 +51,12 @@ from multiprocessing.util import ( get_temp_dir, Finalize, sub_debug, debug, _eintr_retry) try: - from _multiprocessing import win32 - from _subprocess import WAIT_OBJECT_0, WAIT_TIMEOUT, INFINITE + import _winapi + from _winapi import WAIT_OBJECT_0, WAIT_TIMEOUT, INFINITE except ImportError: if sys.platform == 'win32': raise - win32 = None + _winapi = None # # @@ -282,7 +282,7 @@ return self._poll(timeout) -if win32: +if _winapi: class PipeConnection(_ConnectionBase): """ @@ -292,14 +292,14 @@ """ _got_empty_message = False - def _close(self, _CloseHandle=win32.CloseHandle): + def _close(self, _CloseHandle=_winapi.CloseHandle): _CloseHandle(self._handle) def _send_bytes(self, buf): - ov, err = win32.WriteFile(self._handle, buf, overlapped=True) + ov, err = _winapi.WriteFile(self._handle, buf, overlapped=True) try: - if err == win32.ERROR_IO_PENDING: - waitres = win32.WaitForMultipleObjects( + if err == _winapi.ERROR_IO_PENDING: + waitres = _winapi.WaitForMultipleObjects( [ov.event], False, INFINITE) assert waitres == WAIT_OBJECT_0 except: @@ -317,11 +317,11 @@ else: bsize = 128 if maxsize is None else min(maxsize, 128) try: - ov, err = win32.ReadFile(self._handle, bsize, - overlapped=True) + ov, err = _winapi.ReadFile(self._handle, bsize, + overlapped=True) try: - if err == win32.ERROR_IO_PENDING: - waitres = win32.WaitForMultipleObjects( + if err == _winapi.ERROR_IO_PENDING: + waitres = _winapi.WaitForMultipleObjects( [ov.event], False, INFINITE) assert waitres == WAIT_OBJECT_0 except: @@ -333,10 +333,10 @@ f = io.BytesIO() f.write(ov.getbuffer()) return f - elif err == win32.ERROR_MORE_DATA: + elif err == _winapi.ERROR_MORE_DATA: return self._get_more_data(ov, maxsize) except IOError as e: - if e.winerror == win32.ERROR_BROKEN_PIPE: + if e.winerror == _winapi.ERROR_BROKEN_PIPE: raise EOFError else: raise @@ -344,7 +344,7 @@ def _poll(self, timeout): if (self._got_empty_message or - win32.PeekNamedPipe(self._handle)[0] != 0): + _winapi.PeekNamedPipe(self._handle)[0] != 0): return True if timeout < 0: timeout = None @@ -354,11 +354,11 @@ buf = ov.getbuffer() f = io.BytesIO() f.write(buf) - left = win32.PeekNamedPipe(self._handle)[1] + left = _winapi.PeekNamedPipe(self._handle)[1] assert left > 0 if maxsize is not None and len(buf) + left > maxsize: self._bad_message_length() - ov, err = win32.ReadFile(self._handle, left, overlapped=True) + ov, err = _winapi.ReadFile(self._handle, left, overlapped=True) rbytes, err = ov.GetOverlappedResult(True) assert err == 0 assert rbytes == left @@ -372,11 +372,11 @@ a socket handle (Windows). """ - if win32: - def _close(self, _close=win32.closesocket): + if _winapi: + def _close(self, _close=_multiprocessing.closesocket): _close(self._handle) - _write = win32.send - _read = win32.recv + _write = _multiprocessing.send + _read = _multiprocessing.recv else: def _close(self, _close=os.close): _close(self._handle) @@ -526,30 +526,30 @@ ''' address = arbitrary_address('AF_PIPE') if duplex: - openmode = win32.PIPE_ACCESS_DUPLEX - access = win32.GENERIC_READ | win32.GENERIC_WRITE + openmode = _winapi.PIPE_ACCESS_DUPLEX + access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE obsize, ibsize = BUFSIZE, BUFSIZE else: - openmode = win32.PIPE_ACCESS_INBOUND - access = win32.GENERIC_WRITE + openmode = _winapi.PIPE_ACCESS_INBOUND + access = _winapi.GENERIC_WRITE obsize, ibsize = 0, BUFSIZE - h1 = win32.CreateNamedPipe( - address, openmode | win32.FILE_FLAG_OVERLAPPED | - win32.FILE_FLAG_FIRST_PIPE_INSTANCE, - win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | - win32.PIPE_WAIT, - 1, obsize, ibsize, win32.NMPWAIT_WAIT_FOREVER, win32.NULL + h1 = _winapi.CreateNamedPipe( + address, openmode | _winapi.FILE_FLAG_OVERLAPPED | + _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE, + _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE | + _winapi.PIPE_WAIT, + 1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL ) - h2 = win32.CreateFile( - address, access, 0, win32.NULL, win32.OPEN_EXISTING, - win32.FILE_FLAG_OVERLAPPED, win32.NULL + h2 = _winapi.CreateFile( + address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING, + _winapi.FILE_FLAG_OVERLAPPED, _winapi.NULL ) - win32.SetNamedPipeHandleState( - h2, win32.PIPE_READMODE_MESSAGE, None, None + _winapi.SetNamedPipeHandleState( + h2, _winapi.PIPE_READMODE_MESSAGE, None, None ) - overlapped = win32.ConnectNamedPipe(h1, overlapped=True) + overlapped = _winapi.ConnectNamedPipe(h1, overlapped=True) _, err = overlapped.GetOverlappedResult(True) assert err == 0 @@ -630,26 +630,26 @@ ) def _new_handle(self, first=False): - flags = win32.PIPE_ACCESS_DUPLEX | win32.FILE_FLAG_OVERLAPPED + flags = _winapi.PIPE_ACCESS_DUPLEX | _winapi.FILE_FLAG_OVERLAPPED if first: - flags |= win32.FILE_FLAG_FIRST_PIPE_INSTANCE - return win32.CreateNamedPipe( + flags |= _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE + return _winapi.CreateNamedPipe( self._address, flags, - win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | - win32.PIPE_WAIT, - win32.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, - win32.NMPWAIT_WAIT_FOREVER, win32.NULL + _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE | + _winapi.PIPE_WAIT, + _winapi.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, + _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL ) def accept(self): self._handle_queue.append(self._new_handle()) handle = self._handle_queue.pop(0) - ov = win32.ConnectNamedPipe(handle, overlapped=True) + ov = _winapi.ConnectNamedPipe(handle, overlapped=True) try: - res = win32.WaitForMultipleObjects([ov.event], False, INFINITE) + res = _winapi.WaitForMultipleObjects([ov.event], False, INFINITE) except: ov.cancel() - win32.CloseHandle(handle) + _winapi.CloseHandle(handle) raise finally: _, err = ov.GetOverlappedResult(True) @@ -660,7 +660,7 @@ def _finalize_pipe_listener(queue, address): sub_debug('closing listener with address=%r', address) for handle in queue: - win32.CloseHandle(handle) + _winapi.CloseHandle(handle) def PipeClient(address): ''' @@ -669,23 +669,23 @@ t = _init_timeout() while 1: try: - win32.WaitNamedPipe(address, 1000) - h = win32.CreateFile( - address, win32.GENERIC_READ | win32.GENERIC_WRITE, - 0, win32.NULL, win32.OPEN_EXISTING, - win32.FILE_FLAG_OVERLAPPED, win32.NULL + _winapi.WaitNamedPipe(address, 1000) + h = _winapi.CreateFile( + address, _winapi.GENERIC_READ | _winapi.GENERIC_WRITE, + 0, _winapi.NULL, _winapi.OPEN_EXISTING, + _winapi.FILE_FLAG_OVERLAPPED, _winapi.NULL ) except WindowsError as e: - if e.winerror not in (win32.ERROR_SEM_TIMEOUT, - win32.ERROR_PIPE_BUSY) or _check_timeout(t): + if e.winerror not in (_winapi.ERROR_SEM_TIMEOUT, + _winapi.ERROR_PIPE_BUSY) or _check_timeout(t): raise else: break else: raise - win32.SetNamedPipeHandleState( - h, win32.PIPE_READMODE_MESSAGE, None, None + _winapi.SetNamedPipeHandleState( + h, _winapi.PIPE_READMODE_MESSAGE, None, None ) return PipeConnection(h) @@ -774,7 +774,7 @@ L = list(handles) ready = [] while L: - res = win32.WaitForMultipleObjects(L, False, timeout) + res = _winapi.WaitForMultipleObjects(L, False, timeout) if res == WAIT_TIMEOUT: break elif WAIT_OBJECT_0 <= res < WAIT_OBJECT_0 + len(L): @@ -788,7 +788,7 @@ timeout = 0 return ready - _ready_errors = {win32.ERROR_BROKEN_PIPE, win32.ERROR_NETNAME_DELETED} + _ready_errors = {_winapi.ERROR_BROKEN_PIPE, _winapi.ERROR_NETNAME_DELETED} def wait(object_list, timeout=None): ''' @@ -818,12 +818,12 @@ else: # start an overlapped read of length zero try: - ov, err = win32.ReadFile(fileno(), 0, True) + ov, err = _winapi.ReadFile(fileno(), 0, True) except OSError as e: err = e.winerror if err not in _ready_errors: raise - if err == win32.ERROR_IO_PENDING: + if err == _winapi.ERROR_IO_PENDING: ov_list.append(ov) waithandle_to_obj[ov.event] = o else: @@ -847,7 +847,7 @@ err = e.winerror if err not in _ready_errors: raise - if err != win32.ERROR_OPERATION_ABORTED: + if err != _winapi.ERROR_OPERATION_ABORTED: o = waithandle_to_obj[ov.event] ready_objects.add(o) if err == 0: diff --git a/Lib/multiprocessing/forking.py b/Lib/multiprocessing/forking.py --- a/Lib/multiprocessing/forking.py +++ b/Lib/multiprocessing/forking.py @@ -181,10 +181,9 @@ else: import _thread import msvcrt - import _subprocess + import _winapi from pickle import load, HIGHEST_PROTOCOL - from _multiprocessing import win32 def dump(obj, file, protocol=None): ForkingPickler(file, protocol).dump(obj) @@ -197,8 +196,8 @@ WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False)) WINSERVICE = sys.executable.lower().endswith("pythonservice.exe") - exit = win32.ExitProcess - close = win32.CloseHandle + exit = _winapi.ExitProcess + close = _winapi.CloseHandle # # _python_exe is the assumed path to the python executable. @@ -220,11 +219,11 @@ def duplicate(handle, target_process=None, inheritable=False): if target_process is None: - target_process = _subprocess.GetCurrentProcess() - return _subprocess.DuplicateHandle( - _subprocess.GetCurrentProcess(), handle, target_process, - 0, inheritable, _subprocess.DUPLICATE_SAME_ACCESS - ).Detach() + target_process = _winapi.GetCurrentProcess() + return _winapi.DuplicateHandle( + _winapi.GetCurrentProcess(), handle, target_process, + 0, inheritable, _winapi.DUPLICATE_SAME_ACCESS + ) # # We define a Popen class similar to the one from subprocess, but @@ -248,10 +247,10 @@ # start process cmd = get_command_line() + [rhandle] cmd = ' '.join('"%s"' % x for x in cmd) - hp, ht, pid, tid = _subprocess.CreateProcess( + hp, ht, pid, tid = _winapi.CreateProcess( _python_exe, cmd, None, None, 1, 0, None, None, None ) - ht.Close() + _winapi.CloseHandle(ht) close(rhandle) # set attributes of self @@ -282,13 +281,13 @@ def wait(self, timeout=None): if self.returncode is None: if timeout is None: - msecs = _subprocess.INFINITE + msecs = _winapi.INFINITE else: msecs = max(0, int(timeout * 1000 + 0.5)) - res = _subprocess.WaitForSingleObject(int(self._handle), msecs) - if res == _subprocess.WAIT_OBJECT_0: - code = _subprocess.GetExitCodeProcess(self._handle) + res = _winapi.WaitForSingleObject(int(self._handle), msecs) + if res == _winapi.WAIT_OBJECT_0: + code = _winapi.GetExitCodeProcess(self._handle) if code == TERMINATE: code = -signal.SIGTERM self.returncode = code @@ -301,7 +300,7 @@ def terminate(self): if self.returncode is None: try: - _subprocess.TerminateProcess(int(self._handle), TERMINATE) + _winapi.TerminateProcess(int(self._handle), TERMINATE) except WindowsError: if self.wait(timeout=0.1) is None: raise diff --git a/Lib/multiprocessing/heap.py b/Lib/multiprocessing/heap.py --- a/Lib/multiprocessing/heap.py +++ b/Lib/multiprocessing/heap.py @@ -51,7 +51,7 @@ if sys.platform == 'win32': - from _multiprocessing import win32 + import _winapi class Arena(object): @@ -61,7 +61,7 @@ self.size = size self.name = 'pym-%d-%d' % (os.getpid(), next(Arena._counter)) self.buffer = mmap.mmap(-1, self.size, tagname=self.name) - assert win32.GetLastError() == 0, 'tagname already in use' + assert _winapi.GetLastError() == 0, 'tagname already in use' self._state = (self.size, self.name) def __getstate__(self): @@ -71,7 +71,7 @@ def __setstate__(self, state): self.size, self.name = self._state = state self.buffer = mmap.mmap(-1, self.size, tagname=self.name) - assert win32.GetLastError() == win32.ERROR_ALREADY_EXISTS + assert _winapi.GetLastError() == _winapi.ERROR_ALREADY_EXISTS else: diff --git a/Lib/multiprocessing/reduction.py b/Lib/multiprocessing/reduction.py --- a/Lib/multiprocessing/reduction.py +++ b/Lib/multiprocessing/reduction.py @@ -60,11 +60,11 @@ # if sys.platform == 'win32': - from _multiprocessing import win32 + import _winapi def send_handle(conn, handle, destination_pid): - process_handle = win32.OpenProcess( - win32.PROCESS_ALL_ACCESS, False, destination_pid + process_handle = _winapi.OpenProcess( + _winapi.PROCESS_ALL_ACCESS, False, destination_pid ) try: new_handle = duplicate(handle, process_handle) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -385,7 +385,7 @@ if mswindows: import threading import msvcrt - import _subprocess + import _winapi class STARTUPINFO: dwFlags = 0 hStdInput = None @@ -410,15 +410,36 @@ "getoutput", "check_output", "CalledProcessError", "DEVNULL"] if mswindows: - from _subprocess import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP, - STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, - STD_ERROR_HANDLE, SW_HIDE, - STARTF_USESTDHANDLES, STARTF_USESHOWWINDOW) + from _winapi import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP, + STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, + STD_ERROR_HANDLE, SW_HIDE, + STARTF_USESTDHANDLES, STARTF_USESHOWWINDOW) __all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP", "STD_INPUT_HANDLE", "STD_OUTPUT_HANDLE", "STD_ERROR_HANDLE", "SW_HIDE", "STARTF_USESTDHANDLES", "STARTF_USESHOWWINDOW"]) + + class Handle(int): + closed = False + + def Close(self, CloseHandle=_winapi.CloseHandle): + if not self.closed: + self.closed = True + CloseHandle(self) + + def Detach(self): + if not self.closed: + self.closed = True + return int(self) + raise ValueError("already closed") + + def __repr__(self): + return "Handle(%d)" % int(self) + + __del__ = Close + __str__ = __repr__ + try: MAXFD = os.sysconf("SC_OPEN_MAX") except: @@ -892,11 +913,14 @@ errread, errwrite = -1, -1 if stdin is None: - p2cread = _subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE) + p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE) if p2cread is None: - p2cread, _ = _subprocess.CreatePipe(None, 0) + p2cread, _ = _winapi.CreatePipe(None, 0) + p2cread = Handle(p2cread) + _winapi.CloseHandle(_) elif stdin == PIPE: - p2cread, p2cwrite = _subprocess.CreatePipe(None, 0) + p2cread, p2cwrite = _winapi.CreatePipe(None, 0) + p2cread, p2cwrite = Handle(p2cread), Handle(p2cwrite) elif stdin == DEVNULL: p2cread = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdin, int): @@ -907,11 +931,14 @@ p2cread = self._make_inheritable(p2cread) if stdout is None: - c2pwrite = _subprocess.GetStdHandle(_subprocess.STD_OUTPUT_HANDLE) + c2pwrite = _winapi.GetStdHandle(_winapi.STD_OUTPUT_HANDLE) if c2pwrite is None: - _, c2pwrite = _subprocess.CreatePipe(None, 0) + _, c2pwrite = _winapi.CreatePipe(None, 0) + c2pwrite = Handle(c2pwrite) + _winapi.CloseHandle(_) elif stdout == PIPE: - c2pread, c2pwrite = _subprocess.CreatePipe(None, 0) + c2pread, c2pwrite = _winapi.CreatePipe(None, 0) + c2pread, c2pwrite = Handle(c2pread), Handle(c2pwrite) elif stdout == DEVNULL: c2pwrite = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdout, int): @@ -922,11 +949,14 @@ c2pwrite = self._make_inheritable(c2pwrite) if stderr is None: - errwrite = _subprocess.GetStdHandle(_subprocess.STD_ERROR_HANDLE) + errwrite = _winapi.GetStdHandle(_winapi.STD_ERROR_HANDLE) if errwrite is None: - _, errwrite = _subprocess.CreatePipe(None, 0) + _, errwrite = _winapi.CreatePipe(None, 0) + errwrite = Handle(errwrite) + _winapi.CloseHandle(_) elif stderr == PIPE: - errread, errwrite = _subprocess.CreatePipe(None, 0) + errread, errwrite = _winapi.CreatePipe(None, 0) + errread, errwrite = Handle(errread), Handle(errwrite) elif stderr == STDOUT: errwrite = c2pwrite elif stderr == DEVNULL: @@ -945,15 +975,17 @@ def _make_inheritable(self, handle): """Return a duplicate of handle, which is inheritable""" - return _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(), - handle, _subprocess.GetCurrentProcess(), 0, 1, - _subprocess.DUPLICATE_SAME_ACCESS) + h = _winapi.DuplicateHandle( + _winapi.GetCurrentProcess(), handle, + _winapi.GetCurrentProcess(), 0, 1, + _winapi.DUPLICATE_SAME_ACCESS) + return Handle(h) def _find_w9xpopen(self): """Find and return absolut path to w9xpopen.exe""" w9xpopen = os.path.join( - os.path.dirname(_subprocess.GetModuleFileName(0)), + os.path.dirname(_winapi.GetModuleFileName(0)), "w9xpopen.exe") if not os.path.exists(w9xpopen): # Eeek - file-not-found - possibly an embedding @@ -985,17 +1017,17 @@ if startupinfo is None: startupinfo = STARTUPINFO() if -1 not in (p2cread, c2pwrite, errwrite): - startupinfo.dwFlags |= _subprocess.STARTF_USESTDHANDLES + startupinfo.dwFlags |= _winapi.STARTF_USESTDHANDLES startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite startupinfo.hStdError = errwrite if shell: - startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW - startupinfo.wShowWindow = _subprocess.SW_HIDE + startupinfo.dwFlags |= _winapi.STARTF_USESHOWWINDOW + startupinfo.wShowWindow = _winapi.SW_HIDE comspec = os.environ.get("COMSPEC", "cmd.exe") args = '{} /c "{}"'.format (comspec, args) - if (_subprocess.GetVersion() >= 0x80000000 or + if (_winapi.GetVersion() >= 0x80000000 or os.path.basename(comspec).lower() == "command.com"): # Win9x, or using command.com on NT. We need to # use the w9xpopen intermediate program. For more @@ -1009,11 +1041,11 @@ # use at xxx" and a hopeful warning about the # stability of your system. Cost is Ctrl+C won't # kill children. - creationflags |= _subprocess.CREATE_NEW_CONSOLE + creationflags |= _winapi.CREATE_NEW_CONSOLE # Start the process try: - hp, ht, pid, tid = _subprocess.CreateProcess(executable, args, + hp, ht, pid, tid = _winapi.CreateProcess(executable, args, # no special security None, None, int(not close_fds), @@ -1045,14 +1077,14 @@ # Retain the process handle, but close the thread handle self._child_created = True - self._handle = hp + self._handle = Handle(hp) self.pid = pid - ht.Close() + _winapi.CloseHandle(ht) def _internal_poll(self, _deadstate=None, - _WaitForSingleObject=_subprocess.WaitForSingleObject, - _WAIT_OBJECT_0=_subprocess.WAIT_OBJECT_0, - _GetExitCodeProcess=_subprocess.GetExitCodeProcess): + _WaitForSingleObject=_winapi.WaitForSingleObject, + _WAIT_OBJECT_0=_winapi.WAIT_OBJECT_0, + _GetExitCodeProcess=_winapi.GetExitCodeProcess): """Check if child process has terminated. Returns returncode attribute. @@ -1072,15 +1104,15 @@ if endtime is not None: timeout = self._remaining_time(endtime) if timeout is None: - timeout_millis = _subprocess.INFINITE + timeout_millis = _winapi.INFINITE else: timeout_millis = int(timeout * 1000) if self.returncode is None: - result = _subprocess.WaitForSingleObject(self._handle, - timeout_millis) - if result == _subprocess.WAIT_TIMEOUT: + result = _winapi.WaitForSingleObject(self._handle, + timeout_millis) + if result == _winapi.WAIT_TIMEOUT: raise TimeoutExpired(self.args, timeout) - self.returncode = _subprocess.GetExitCodeProcess(self._handle) + self.returncode = _winapi.GetExitCodeProcess(self._handle) return self.returncode @@ -1163,12 +1195,12 @@ """Terminates the process """ try: - _subprocess.TerminateProcess(self._handle, 1) + _winapi.TerminateProcess(self._handle, 1) except PermissionError: # ERROR_ACCESS_DENIED (winerror 5) is received when the # process already died. - rc = _subprocess.GetExitCodeProcess(self._handle) - if rc == _subprocess.STILL_ACTIVE: + rc = _winapi.GetExitCodeProcess(self._handle) + if rc == _winapi.STILL_ACTIVE: raise self.returncode = rc diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -84,7 +84,7 @@ WIN32 = (sys.platform == "win32") if WIN32: - from _subprocess import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 + from _winapi import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 def wait_for_handle(handle, timeout): if timeout is None or timeout < 0.0: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,10 @@ Library ------- +- Issue #11750: The Windows API functions scattered in the _subprocess and + _multiprocessing.win32 modules now live in a single module "_winapi". + Patch by sbt. + - Issue #14087: multiprocessing: add Condition.wait_for(). Patch by sbt. - Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -9,8 +9,6 @@ #include "multiprocessing.h" -PyObject *create_win32_namespace(void); - PyObject *ProcessError, *BufferTooShort; /* @@ -66,6 +64,72 @@ PyLong_FromVoidPtr(buffer), buffer_len); } +#ifdef MS_WINDOWS +static PyObject * +multiprocessing_closesocket(PyObject *self, PyObject *args) +{ + HANDLE handle; + int ret; + + if (!PyArg_ParseTuple(args, F_HANDLE ":closesocket" , &handle)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + ret = closesocket((SOCKET) handle); + Py_END_ALLOW_THREADS + + if (ret) + return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); + Py_RETURN_NONE; +} + +static PyObject * +multiprocessing_recv(PyObject *self, PyObject *args) +{ + HANDLE handle; + int size, nread; + PyObject *buf; + + if (!PyArg_ParseTuple(args, F_HANDLE "i:recv" , &handle, &size)) + return NULL; + + buf = PyBytes_FromStringAndSize(NULL, size); + if (!buf) + return NULL; + + Py_BEGIN_ALLOW_THREADS + nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0); + Py_END_ALLOW_THREADS + + if (nread < 0) { + Py_DECREF(buf); + return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); + } + _PyBytes_Resize(&buf, nread); + return buf; +} + +static PyObject * +multiprocessing_send(PyObject *self, PyObject *args) +{ + HANDLE handle; + Py_buffer buf; + int ret; + + if (!PyArg_ParseTuple(args, F_HANDLE "y*:send" , &handle, &buf)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + ret = send((SOCKET) handle, buf.buf, buf.len, 0); + Py_END_ALLOW_THREADS + + PyBuffer_Release(&buf); + if (ret < 0) + return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); + return PyLong_FromLong(ret); +} + +#endif /* * Function table @@ -75,6 +139,11 @@ {"address_of_buffer", multiprocessing_address_of_buffer, METH_O, "address_of_buffer(obj) -> int\n" "Return address of obj assuming obj supports buffer inteface"}, +#ifdef MS_WINDOWS + {"closesocket", multiprocessing_closesocket, METH_VARARGS, ""}, + {"recv", multiprocessing_recv, METH_VARARGS, ""}, + {"send", multiprocessing_send, METH_VARARGS, ""}, +#endif {NULL} }; @@ -135,14 +204,6 @@ PyModule_AddObject(module, "SemLock", (PyObject*)&SemLockType); #endif -#ifdef MS_WINDOWS - /* Initialize win32 class and add to multiprocessing */ - temp = create_win32_namespace(); - if (!temp) - return NULL; - PyModule_AddObject(module, "win32", temp); -#endif - /* Add configuration macros */ temp = PyDict_New(); if (!temp) @@ -152,7 +213,7 @@ value = Py_BuildValue("i", name); \ if (value == NULL) { Py_DECREF(temp); return NULL; } \ if (PyDict_SetItemString(temp, #name, value) < 0) { \ - Py_DECREF(temp); Py_DECREF(value); return NULL; } \ + Py_DECREF(temp); Py_DECREF(value); return NULL; } \ Py_DECREF(value) #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) diff --git a/Modules/_multiprocessing/win32_functions.c b/Modules/_multiprocessing/win32_functions.c deleted file mode 100644 --- a/Modules/_multiprocessing/win32_functions.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - * Win32 functions used by multiprocessing package - * - * win32_functions.c - * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt - */ - -#include "multiprocessing.h" - - -#define WIN32_FUNCTION(func) \ - {#func, (PyCFunction)win32_ ## func, METH_VARARGS | METH_STATIC, ""} - -#define WIN32_KWARGS_FUNCTION(func) \ - {#func, (PyCFunction)win32_ ## func, METH_VARARGS | METH_KEYWORDS | METH_STATIC, ""} - -#define WIN32_CONSTANT(fmt, con) \ - PyDict_SetItemString(Win32Type.tp_dict, #con, Py_BuildValue(fmt, con)) - - -/* Grab CancelIoEx dynamically from kernel32 */ -static int has_CancelIoEx = -1; -static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED); - -static int -check_CancelIoEx() -{ - if (has_CancelIoEx == -1) - { - HINSTANCE hKernel32 = GetModuleHandle("KERNEL32"); - * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32, - "CancelIoEx"); - has_CancelIoEx = (Py_CancelIoEx != NULL); - } - return has_CancelIoEx; -} - - -/* - * A Python object wrapping an OVERLAPPED structure and other useful data - * for overlapped I/O - */ - -typedef struct { - PyObject_HEAD - OVERLAPPED overlapped; - /* For convenience, we store the file handle too */ - HANDLE handle; - /* Whether there's I/O in flight */ - int pending; - /* Whether I/O completed successfully */ - int completed; - /* Buffer used for reading (optional) */ - PyObject *read_buffer; - /* Buffer used for writing (optional) */ - Py_buffer write_buffer; -} OverlappedObject; - -static void -overlapped_dealloc(OverlappedObject *self) -{ - DWORD bytes; - int err = GetLastError(); - if (self->pending) { - /* make it a programming error to deallocate while operation - is pending, even if we can safely cancel it */ - if (check_CancelIoEx() && - Py_CancelIoEx(self->handle, &self->overlapped)) - GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE); - PyErr_SetString(PyExc_RuntimeError, - "I/O operations still in flight while destroying " - "Overlapped object, the process may crash"); - PyErr_WriteUnraisable(NULL); - } - CloseHandle(self->overlapped.hEvent); - SetLastError(err); - if (self->write_buffer.obj) - PyBuffer_Release(&self->write_buffer); - Py_CLEAR(self->read_buffer); - PyObject_Del(self); -} - -static PyObject * -overlapped_GetOverlappedResult(OverlappedObject *self, PyObject *waitobj) -{ - int wait; - BOOL res; - DWORD transferred = 0; - DWORD err; - - wait = PyObject_IsTrue(waitobj); - if (wait < 0) - return NULL; - Py_BEGIN_ALLOW_THREADS - res = GetOverlappedResult(self->handle, &self->overlapped, &transferred, - wait != 0); - Py_END_ALLOW_THREADS - - err = res ? ERROR_SUCCESS : GetLastError(); - switch (err) { - case ERROR_SUCCESS: - case ERROR_MORE_DATA: - case ERROR_OPERATION_ABORTED: - self->completed = 1; - self->pending = 0; - break; - case ERROR_IO_INCOMPLETE: - break; - default: - self->pending = 0; - return PyErr_SetExcFromWindowsErr(PyExc_IOError, err); - } - if (self->completed && self->read_buffer != NULL) { - assert(PyBytes_CheckExact(self->read_buffer)); - if (transferred != PyBytes_GET_SIZE(self->read_buffer) && - _PyBytes_Resize(&self->read_buffer, transferred)) - return NULL; - } - return Py_BuildValue("II", (unsigned) transferred, (unsigned) err); -} - -static PyObject * -overlapped_getbuffer(OverlappedObject *self) -{ - PyObject *res; - if (!self->completed) { - PyErr_SetString(PyExc_ValueError, - "can't get read buffer before GetOverlappedResult() " - "signals the operation completed"); - return NULL; - } - res = self->read_buffer ? self->read_buffer : Py_None; - Py_INCREF(res); - return res; -} - -static PyObject * -overlapped_cancel(OverlappedObject *self) -{ - BOOL res = TRUE; - - if (self->pending) { - Py_BEGIN_ALLOW_THREADS - if (check_CancelIoEx()) - res = Py_CancelIoEx(self->handle, &self->overlapped); - else - res = CancelIo(self->handle); - Py_END_ALLOW_THREADS - } - - /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */ - if (!res && GetLastError() != ERROR_NOT_FOUND) - return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - self->pending = 0; - Py_RETURN_NONE; -} - -static PyMethodDef overlapped_methods[] = { - {"GetOverlappedResult", (PyCFunction) overlapped_GetOverlappedResult, - METH_O, NULL}, - {"getbuffer", (PyCFunction) overlapped_getbuffer, METH_NOARGS, NULL}, - {"cancel", (PyCFunction) overlapped_cancel, METH_NOARGS, NULL}, - {NULL} -}; - -static PyMemberDef overlapped_members[] = { - {"event", T_HANDLE, - offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent), - READONLY, "overlapped event handle"}, - {NULL} -}; - -PyTypeObject OverlappedType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_multiprocessing.win32.Overlapped", - /* tp_basicsize */ sizeof(OverlappedObject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor) overlapped_dealloc, - /* 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 */ 0, - /* tp_getattro */ 0, - /* tp_setattro */ 0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT, - /* tp_doc */ "OVERLAPPED structure wrapper", - /* tp_traverse */ 0, - /* tp_clear */ 0, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ 0, - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ overlapped_methods, - /* tp_members */ overlapped_members, - /* 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 */ 0, - /* tp_new */ 0, -}; - -static OverlappedObject * -new_overlapped(HANDLE handle) -{ - OverlappedObject *self; - - self = PyObject_New(OverlappedObject, &OverlappedType); - if (!self) - return NULL; - self->handle = handle; - self->read_buffer = NULL; - self->pending = 0; - self->completed = 0; - memset(&self->overlapped, 0, sizeof(OVERLAPPED)); - memset(&self->write_buffer, 0, sizeof(Py_buffer)); - /* Manual reset, initially non-signalled */ - self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - return self; -} - - -/* - * Module functions - */ - -static PyObject * -win32_CloseHandle(PyObject *self, PyObject *args) -{ - HANDLE hObject; - BOOL success; - - if (!PyArg_ParseTuple(args, F_HANDLE, &hObject)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - success = CloseHandle(hObject); - Py_END_ALLOW_THREADS - - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_ConnectNamedPipe(PyObject *self, PyObject *args, PyObject *kwds) -{ - HANDLE hNamedPipe; - int use_overlapped = 0; - BOOL success; - OverlappedObject *overlapped = NULL; - static char *kwlist[] = {"handle", "overlapped", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - F_HANDLE "|i", kwlist, - &hNamedPipe, &use_overlapped)) - return NULL; - - if (use_overlapped) { - overlapped = new_overlapped(hNamedPipe); - if (!overlapped) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - success = ConnectNamedPipe(hNamedPipe, - overlapped ? &overlapped->overlapped : NULL); - Py_END_ALLOW_THREADS - - if (overlapped) { - int err = GetLastError(); - /* Overlapped ConnectNamedPipe never returns a success code */ - assert(success == 0); - if (err == ERROR_IO_PENDING) - overlapped->pending = 1; - else if (err == ERROR_PIPE_CONNECTED) - SetEvent(overlapped->overlapped.hEvent); - else { - Py_DECREF(overlapped); - return PyErr_SetFromWindowsErr(err); - } - return (PyObject *) overlapped; - } - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_CreateFile(PyObject *self, PyObject *args) -{ - LPCTSTR lpFileName; - DWORD dwDesiredAccess; - DWORD dwShareMode; - LPSECURITY_ATTRIBUTES lpSecurityAttributes; - DWORD dwCreationDisposition; - DWORD dwFlagsAndAttributes; - HANDLE hTemplateFile; - HANDLE handle; - - if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_POINTER - F_DWORD F_DWORD F_HANDLE, - &lpFileName, &dwDesiredAccess, &dwShareMode, - &lpSecurityAttributes, &dwCreationDisposition, - &dwFlagsAndAttributes, &hTemplateFile)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - handle = CreateFile(lpFileName, dwDesiredAccess, - dwShareMode, lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, hTemplateFile); - Py_END_ALLOW_THREADS - - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_CreateNamedPipe(PyObject *self, PyObject *args) -{ - LPCTSTR lpName; - DWORD dwOpenMode; - DWORD dwPipeMode; - DWORD nMaxInstances; - DWORD nOutBufferSize; - DWORD nInBufferSize; - DWORD nDefaultTimeOut; - LPSECURITY_ATTRIBUTES lpSecurityAttributes; - HANDLE handle; - - if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_DWORD - F_DWORD F_DWORD F_DWORD F_POINTER, - &lpName, &dwOpenMode, &dwPipeMode, - &nMaxInstances, &nOutBufferSize, - &nInBufferSize, &nDefaultTimeOut, - &lpSecurityAttributes)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode, - nMaxInstances, nOutBufferSize, - nInBufferSize, nDefaultTimeOut, - lpSecurityAttributes); - Py_END_ALLOW_THREADS - - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_ExitProcess(PyObject *self, PyObject *args) -{ - UINT uExitCode; - - if (!PyArg_ParseTuple(args, "I", &uExitCode)) - return NULL; - - #if defined(Py_DEBUG) - SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); - #endif - - - ExitProcess(uExitCode); - - return NULL; -} - -static PyObject * -win32_GetLastError(PyObject *self, PyObject *args) -{ - return Py_BuildValue(F_DWORD, GetLastError()); -} - -static PyObject * -win32_OpenProcess(PyObject *self, PyObject *args) -{ - DWORD dwDesiredAccess; - BOOL bInheritHandle; - DWORD dwProcessId; - HANDLE handle; - - if (!PyArg_ParseTuple(args, F_DWORD "i" F_DWORD, - &dwDesiredAccess, &bInheritHandle, &dwProcessId)) - return NULL; - - handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); - if (handle == NULL) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_SetNamedPipeHandleState(PyObject *self, PyObject *args) -{ - HANDLE hNamedPipe; - PyObject *oArgs[3]; - DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL}; - int i; - - if (!PyArg_ParseTuple(args, F_HANDLE "OOO", - &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2])) - return NULL; - - PyErr_Clear(); - - for (i = 0 ; i < 3 ; i++) { - if (oArgs[i] != Py_None) { - dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]); - if (PyErr_Occurred()) - return NULL; - pArgs[i] = &dwArgs[i]; - } - } - - if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2])) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_WaitNamedPipe(PyObject *self, PyObject *args) -{ - LPCTSTR lpNamedPipeName; - DWORD nTimeOut; - BOOL success; - - if (!PyArg_ParseTuple(args, "s" F_DWORD, &lpNamedPipeName, &nTimeOut)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - success = WaitNamedPipe(lpNamedPipeName, nTimeOut); - Py_END_ALLOW_THREADS - - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_closesocket(PyObject *self, PyObject *args) -{ - HANDLE handle; - int ret; - - if (!PyArg_ParseTuple(args, F_HANDLE ":closesocket" , &handle)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - ret = closesocket((SOCKET) handle); - Py_END_ALLOW_THREADS - - if (ret) - return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); - Py_RETURN_NONE; -} - -static PyObject * -win32_recv(PyObject *self, PyObject *args) -{ - HANDLE handle; - int size, nread; - PyObject *buf; - - if (!PyArg_ParseTuple(args, F_HANDLE "i:recv" , &handle, &size)) - return NULL; - - buf = PyBytes_FromStringAndSize(NULL, size); - if (!buf) - return NULL; - - Py_BEGIN_ALLOW_THREADS - nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0); - Py_END_ALLOW_THREADS - - if (nread < 0) { - Py_DECREF(buf); - return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); - } - _PyBytes_Resize(&buf, nread); - return buf; -} - -static PyObject * -win32_send(PyObject *self, PyObject *args) -{ - HANDLE handle; - Py_buffer buf; - int ret; - - if (!PyArg_ParseTuple(args, F_HANDLE "y*:send" , &handle, &buf)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - ret = send((SOCKET) handle, buf.buf, buf.len, 0); - Py_END_ALLOW_THREADS - - PyBuffer_Release(&buf); - if (ret < 0) - return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); - return PyLong_FromLong(ret); -} - -static PyObject * -win32_WriteFile(PyObject *self, PyObject *args, PyObject *kwds) -{ - HANDLE handle; - Py_buffer _buf, *buf; - PyObject *bufobj; - DWORD written; - BOOL ret; - int use_overlapped = 0; - DWORD err; - OverlappedObject *overlapped = NULL; - static char *kwlist[] = {"handle", "buffer", "overlapped", NULL}; - - /* First get handle and use_overlapped to know which Py_buffer to use */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, - F_HANDLE "O|i:WriteFile", kwlist, - &handle, &bufobj, &use_overlapped)) - return NULL; - - if (use_overlapped) { - overlapped = new_overlapped(handle); - if (!overlapped) - return NULL; - buf = &overlapped->write_buffer; - } - else - buf = &_buf; - - if (!PyArg_Parse(bufobj, "y*", buf)) { - Py_XDECREF(overlapped); - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - ret = WriteFile(handle, buf->buf, buf->len, &written, - overlapped ? &overlapped->overlapped : NULL); - Py_END_ALLOW_THREADS - - err = ret ? 0 : GetLastError(); - - if (overlapped) { - if (!ret) { - if (err == ERROR_IO_PENDING) - overlapped->pending = 1; - else { - Py_DECREF(overlapped); - return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - } - } - return Py_BuildValue("NI", (PyObject *) overlapped, err); - } - - PyBuffer_Release(buf); - if (!ret) - return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - return Py_BuildValue("II", written, err); -} - -static PyObject * -win32_ReadFile(PyObject *self, PyObject *args, PyObject *kwds) -{ - HANDLE handle; - int size; - DWORD nread; - PyObject *buf; - BOOL ret; - int use_overlapped = 0; - DWORD err; - OverlappedObject *overlapped = NULL; - static char *kwlist[] = {"handle", "size", "overlapped", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - F_HANDLE "i|i:ReadFile", kwlist, - &handle, &size, &use_overlapped)) - return NULL; - - buf = PyBytes_FromStringAndSize(NULL, size); - if (!buf) - return NULL; - if (use_overlapped) { - overlapped = new_overlapped(handle); - if (!overlapped) { - Py_DECREF(buf); - return NULL; - } - /* Steals reference to buf */ - overlapped->read_buffer = buf; - } - - Py_BEGIN_ALLOW_THREADS - ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread, - overlapped ? &overlapped->overlapped : NULL); - Py_END_ALLOW_THREADS - - err = ret ? 0 : GetLastError(); - - if (overlapped) { - if (!ret) { - if (err == ERROR_IO_PENDING) - overlapped->pending = 1; - else if (err != ERROR_MORE_DATA) { - Py_DECREF(overlapped); - return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - } - } - return Py_BuildValue("NI", (PyObject *) overlapped, err); - } - - if (!ret && err != ERROR_MORE_DATA) { - Py_DECREF(buf); - return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - } - if (_PyBytes_Resize(&buf, nread)) - return NULL; - return Py_BuildValue("NI", buf, err); -} - -static PyObject * -win32_PeekNamedPipe(PyObject *self, PyObject *args) -{ - HANDLE handle; - int size = 0; - PyObject *buf = NULL; - DWORD nread, navail, nleft; - BOOL ret; - - if (!PyArg_ParseTuple(args, F_HANDLE "|i:PeekNamedPipe" , &handle, &size)) - return NULL; - - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative size"); - return NULL; - } - - if (size) { - buf = PyBytes_FromStringAndSize(NULL, size); - if (!buf) - return NULL; - Py_BEGIN_ALLOW_THREADS - ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread, - &navail, &nleft); - Py_END_ALLOW_THREADS - if (!ret) { - Py_DECREF(buf); - return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - } - if (_PyBytes_Resize(&buf, nread)) - return NULL; - return Py_BuildValue("Nii", buf, navail, nleft); - } - else { - Py_BEGIN_ALLOW_THREADS - ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft); - Py_END_ALLOW_THREADS - if (!ret) { - return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - } - return Py_BuildValue("ii", navail, nleft); - } -} - -static PyObject * -win32_WaitForMultipleObjects(PyObject* self, PyObject* args) -{ - DWORD result; - PyObject *handle_seq; - HANDLE handles[MAXIMUM_WAIT_OBJECTS]; - HANDLE sigint_event = NULL; - Py_ssize_t nhandles, i; - int wait_flag; - int milliseconds = INFINITE; - - if (!PyArg_ParseTuple(args, "Oi|i:WaitForMultipleObjects", - &handle_seq, &wait_flag, &milliseconds)) - return NULL; - - if (!PySequence_Check(handle_seq)) { - PyErr_Format(PyExc_TypeError, - "sequence type expected, got '%s'", - Py_TYPE(handle_seq)->tp_doc); - return NULL; - } - nhandles = PySequence_Length(handle_seq); - if (nhandles == -1) - return NULL; - if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) { - PyErr_Format(PyExc_ValueError, - "need at most %zd handles, got a sequence of length %zd", - MAXIMUM_WAIT_OBJECTS - 1, nhandles); - return NULL; - } - for (i = 0; i < nhandles; i++) { - HANDLE h; - PyObject *v = PySequence_GetItem(handle_seq, i); - if (v == NULL) - return NULL; - if (!PyArg_Parse(v, F_HANDLE, &h)) { - Py_DECREF(v); - return NULL; - } - handles[i] = h; - Py_DECREF(v); - } - /* If this is the main thread then make the wait interruptible - by Ctrl-C unless we are waiting for *all* handles */ - if (!wait_flag && _PyOS_IsMainThread()) { - sigint_event = _PyOS_SigintEvent(); - assert(sigint_event != NULL); - handles[nhandles++] = sigint_event; - } - - Py_BEGIN_ALLOW_THREADS - if (sigint_event != NULL) - ResetEvent(sigint_event); - result = WaitForMultipleObjects((DWORD) nhandles, handles, - (BOOL) wait_flag, (DWORD) milliseconds); - Py_END_ALLOW_THREADS - - if (result == WAIT_FAILED) - return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) { - errno = EINTR; - return PyErr_SetFromErrno(PyExc_IOError); - } - - return PyLong_FromLong((int) result); -} - - -static PyMethodDef win32_methods[] = { - WIN32_FUNCTION(CloseHandle), - WIN32_FUNCTION(GetLastError), - WIN32_FUNCTION(OpenProcess), - WIN32_FUNCTION(ExitProcess), - WIN32_KWARGS_FUNCTION(ConnectNamedPipe), - WIN32_FUNCTION(CreateFile), - WIN32_FUNCTION(CreateNamedPipe), - WIN32_KWARGS_FUNCTION(ReadFile), - WIN32_FUNCTION(PeekNamedPipe), - WIN32_FUNCTION(SetNamedPipeHandleState), - WIN32_FUNCTION(WaitForMultipleObjects), - WIN32_FUNCTION(WaitNamedPipe), - WIN32_KWARGS_FUNCTION(WriteFile), - WIN32_FUNCTION(closesocket), - WIN32_FUNCTION(recv), - WIN32_FUNCTION(send), - {NULL} -}; - - -PyTypeObject Win32Type = { - PyVarObject_HEAD_INIT(NULL, 0) -}; - - -PyObject * -create_win32_namespace(void) -{ - Win32Type.tp_name = "_multiprocessing.win32"; - Win32Type.tp_methods = win32_methods; - if (PyType_Ready(&Win32Type) < 0) - return NULL; - Py_INCREF(&Win32Type); - - if (PyType_Ready(&OverlappedType) < 0) - return NULL; - PyDict_SetItemString(Win32Type.tp_dict, "Overlapped", - (PyObject *) &OverlappedType); - - WIN32_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS); - WIN32_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE); - WIN32_CONSTANT(F_DWORD, ERROR_IO_PENDING); - WIN32_CONSTANT(F_DWORD, ERROR_MORE_DATA); - WIN32_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); - WIN32_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); - WIN32_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED); - WIN32_CONSTANT(F_DWORD, ERROR_PIPE_BUSY); - WIN32_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED); - WIN32_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT); - WIN32_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE); - WIN32_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED); - WIN32_CONSTANT(F_DWORD, GENERIC_READ); - WIN32_CONSTANT(F_DWORD, GENERIC_WRITE); - WIN32_CONSTANT(F_DWORD, INFINITE); - WIN32_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER); - WIN32_CONSTANT(F_DWORD, OPEN_EXISTING); - WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX); - WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND); - WIN32_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE); - WIN32_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE); - WIN32_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES); - WIN32_CONSTANT(F_DWORD, PIPE_WAIT); - WIN32_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS); - - WIN32_CONSTANT("i", NULL); - - return (PyObject*)&Win32Type; -} diff --git a/Modules/_winapi.c b/Modules/_winapi.c new file mode 100644 --- /dev/null +++ b/Modules/_winapi.c @@ -0,0 +1,1326 @@ +/* + * Support routines from the Windows API + * + * This module was originally created by merging PC/_subprocess.c with + * Modules/_multiprocessing/win32_functions.c. + * + * Copyright (c) 2004 by Fredrik Lundh + * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com + * Copyright (c) 2004 by Peter Astrand + * + * By obtaining, using, and/or copying this software and/or its + * associated documentation, you agree that you have read, understood, + * and will comply with the following terms and conditions: + * + * Permission to use, copy, modify, and distribute this software and + * its associated documentation for any purpose and without fee is + * hereby granted, provided that the above copyright notice appears in + * all copies, and that both that copyright notice and this permission + * notice appear in supporting documentation, and that the name of the + * authors not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Licensed to PSF under a Contributor Agreement. */ +/* See http://www.python.org/2.4/license for licensing details. */ + +#include "Python.h" +#include "structmember.h" + +#define WINDOWS_LEAN_AND_MEAN +#include "windows.h" +#include + +#if defined(MS_WIN32) && !defined(MS_WIN64) +#define HANDLE_TO_PYNUM(handle) \ + PyLong_FromUnsignedLong((unsigned long) handle) +#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj)) +#define F_POINTER "k" +#define T_POINTER T_ULONG +#else +#define HANDLE_TO_PYNUM(handle) \ + PyLong_FromUnsignedLongLong((unsigned long long) handle) +#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj)) +#define F_POINTER "K" +#define T_POINTER T_ULONGLONG +#endif + +#define F_HANDLE F_POINTER +#define F_DWORD "k" +#define F_BOOL "i" +#define F_UINT "I" + +#define T_HANDLE T_POINTER + +/* Grab CancelIoEx dynamically from kernel32 */ +static int has_CancelIoEx = -1; +static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED); + +static int +check_CancelIoEx() +{ + if (has_CancelIoEx == -1) + { + HINSTANCE hKernel32 = GetModuleHandle("KERNEL32"); + * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32, + "CancelIoEx"); + has_CancelIoEx = (Py_CancelIoEx != NULL); + } + return has_CancelIoEx; +} + + +/* + * A Python object wrapping an OVERLAPPED structure and other useful data + * for overlapped I/O + */ + +typedef struct { + PyObject_HEAD + OVERLAPPED overlapped; + /* For convenience, we store the file handle too */ + HANDLE handle; + /* Whether there's I/O in flight */ + int pending; + /* Whether I/O completed successfully */ + int completed; + /* Buffer used for reading (optional) */ + PyObject *read_buffer; + /* Buffer used for writing (optional) */ + Py_buffer write_buffer; +} OverlappedObject; + +static void +overlapped_dealloc(OverlappedObject *self) +{ + DWORD bytes; + int err = GetLastError(); + if (self->pending) { + /* make it a programming error to deallocate while operation + is pending, even if we can safely cancel it */ + if (check_CancelIoEx() && + Py_CancelIoEx(self->handle, &self->overlapped)) + GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE); + PyErr_SetString(PyExc_RuntimeError, + "I/O operations still in flight while destroying " + "Overlapped object, the process may crash"); + PyErr_WriteUnraisable(NULL); + } + CloseHandle(self->overlapped.hEvent); + SetLastError(err); + if (self->write_buffer.obj) + PyBuffer_Release(&self->write_buffer); + Py_CLEAR(self->read_buffer); + PyObject_Del(self); +} + +static PyObject * +overlapped_GetOverlappedResult(OverlappedObject *self, PyObject *waitobj) +{ + int wait; + BOOL res; + DWORD transferred = 0; + DWORD err; + + wait = PyObject_IsTrue(waitobj); + if (wait < 0) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = GetOverlappedResult(self->handle, &self->overlapped, &transferred, + wait != 0); + Py_END_ALLOW_THREADS + + err = res ? ERROR_SUCCESS : GetLastError(); + switch (err) { + case ERROR_SUCCESS: + case ERROR_MORE_DATA: + case ERROR_OPERATION_ABORTED: + self->completed = 1; + self->pending = 0; + break; + case ERROR_IO_INCOMPLETE: + break; + default: + self->pending = 0; + return PyErr_SetExcFromWindowsErr(PyExc_IOError, err); + } + if (self->completed && self->read_buffer != NULL) { + assert(PyBytes_CheckExact(self->read_buffer)); + if (transferred != PyBytes_GET_SIZE(self->read_buffer) && + _PyBytes_Resize(&self->read_buffer, transferred)) + return NULL; + } + return Py_BuildValue("II", (unsigned) transferred, (unsigned) err); +} + +static PyObject * +overlapped_getbuffer(OverlappedObject *self) +{ + PyObject *res; + if (!self->completed) { + PyErr_SetString(PyExc_ValueError, + "can't get read buffer before GetOverlappedResult() " + "signals the operation completed"); + return NULL; + } + res = self->read_buffer ? self->read_buffer : Py_None; + Py_INCREF(res); + return res; +} + +static PyObject * +overlapped_cancel(OverlappedObject *self) +{ + BOOL res = TRUE; + + if (self->pending) { + Py_BEGIN_ALLOW_THREADS + if (check_CancelIoEx()) + res = Py_CancelIoEx(self->handle, &self->overlapped); + else + res = CancelIo(self->handle); + Py_END_ALLOW_THREADS + } + + /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */ + if (!res && GetLastError() != ERROR_NOT_FOUND) + return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); + self->pending = 0; + Py_RETURN_NONE; +} + +static PyMethodDef overlapped_methods[] = { + {"GetOverlappedResult", (PyCFunction) overlapped_GetOverlappedResult, + METH_O, NULL}, + {"getbuffer", (PyCFunction) overlapped_getbuffer, METH_NOARGS, NULL}, + {"cancel", (PyCFunction) overlapped_cancel, METH_NOARGS, NULL}, + {NULL} +}; + +static PyMemberDef overlapped_members[] = { + {"event", T_HANDLE, + offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent), + READONLY, "overlapped event handle"}, + {NULL} +}; + +PyTypeObject OverlappedType = { + PyVarObject_HEAD_INIT(NULL, 0) + /* tp_name */ "_winapi.Overlapped", + /* tp_basicsize */ sizeof(OverlappedObject), + /* tp_itemsize */ 0, + /* tp_dealloc */ (destructor) overlapped_dealloc, + /* 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 */ 0, + /* tp_getattro */ 0, + /* tp_setattro */ 0, + /* tp_as_buffer */ 0, + /* tp_flags */ Py_TPFLAGS_DEFAULT, + /* tp_doc */ "OVERLAPPED structure wrapper", + /* tp_traverse */ 0, + /* tp_clear */ 0, + /* tp_richcompare */ 0, + /* tp_weaklistoffset */ 0, + /* tp_iter */ 0, + /* tp_iternext */ 0, + /* tp_methods */ overlapped_methods, + /* tp_members */ overlapped_members, + /* 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 */ 0, + /* tp_new */ 0, +}; + +static OverlappedObject * +new_overlapped(HANDLE handle) +{ + OverlappedObject *self; + + self = PyObject_New(OverlappedObject, &OverlappedType); + if (!self) + return NULL; + self->handle = handle; + self->read_buffer = NULL; + self->pending = 0; + self->completed = 0; + memset(&self->overlapped, 0, sizeof(OVERLAPPED)); + memset(&self->write_buffer, 0, sizeof(Py_buffer)); + /* Manual reset, initially non-signalled */ + self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + return self; +} + +/* -------------------------------------------------------------------- */ +/* windows API functions */ + +PyDoc_STRVAR(CloseHandle_doc, +"CloseHandle(handle) -> None\n\ +\n\ +Close handle."); + +static PyObject * +winapi_CloseHandle(PyObject *self, PyObject *args) +{ + HANDLE hObject; + BOOL success; + + if (!PyArg_ParseTuple(args, F_HANDLE ":CloseHandle", &hObject)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + success = CloseHandle(hObject); + Py_END_ALLOW_THREADS + + if (!success) + return PyErr_SetFromWindowsErr(0); + + Py_RETURN_NONE; +} + +static PyObject * +winapi_ConnectNamedPipe(PyObject *self, PyObject *args, PyObject *kwds) +{ + HANDLE hNamedPipe; + int use_overlapped = 0; + BOOL success; + OverlappedObject *overlapped = NULL; + static char *kwlist[] = {"handle", "overlapped", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, + F_HANDLE "|" F_BOOL, kwlist, + &hNamedPipe, &use_overlapped)) + return NULL; + + if (use_overlapped) { + overlapped = new_overlapped(hNamedPipe); + if (!overlapped) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + success = ConnectNamedPipe(hNamedPipe, + overlapped ? &overlapped->overlapped : NULL); + Py_END_ALLOW_THREADS + + if (overlapped) { + int err = GetLastError(); + /* Overlapped ConnectNamedPipe never returns a success code */ + assert(success == 0); + if (err == ERROR_IO_PENDING) + overlapped->pending = 1; + else if (err == ERROR_PIPE_CONNECTED) + SetEvent(overlapped->overlapped.hEvent); + else { + Py_DECREF(overlapped); + return PyErr_SetFromWindowsErr(err); + } + return (PyObject *) overlapped; + } + if (!success) + return PyErr_SetFromWindowsErr(0); + + Py_RETURN_NONE; +} + +static PyObject * +winapi_CreateFile(PyObject *self, PyObject *args) +{ + LPCTSTR lpFileName; + DWORD dwDesiredAccess; + DWORD dwShareMode; + LPSECURITY_ATTRIBUTES lpSecurityAttributes; + DWORD dwCreationDisposition; + DWORD dwFlagsAndAttributes; + HANDLE hTemplateFile; + HANDLE handle; + + if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_POINTER + F_DWORD F_DWORD F_HANDLE, + &lpFileName, &dwDesiredAccess, &dwShareMode, + &lpSecurityAttributes, &dwCreationDisposition, + &dwFlagsAndAttributes, &hTemplateFile)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + handle = CreateFile(lpFileName, dwDesiredAccess, + dwShareMode, lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, hTemplateFile); + Py_END_ALLOW_THREADS + + if (handle == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(0); + + return Py_BuildValue(F_HANDLE, handle); +} + +static PyObject * +winapi_CreateNamedPipe(PyObject *self, PyObject *args) +{ + LPCTSTR lpName; + DWORD dwOpenMode; + DWORD dwPipeMode; + DWORD nMaxInstances; + DWORD nOutBufferSize; + DWORD nInBufferSize; + DWORD nDefaultTimeOut; + LPSECURITY_ATTRIBUTES lpSecurityAttributes; + HANDLE handle; + + if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_DWORD + F_DWORD F_DWORD F_DWORD F_POINTER, + &lpName, &dwOpenMode, &dwPipeMode, + &nMaxInstances, &nOutBufferSize, + &nInBufferSize, &nDefaultTimeOut, + &lpSecurityAttributes)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode, + nMaxInstances, nOutBufferSize, + nInBufferSize, nDefaultTimeOut, + lpSecurityAttributes); + Py_END_ALLOW_THREADS + + if (handle == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(0); + + return Py_BuildValue(F_HANDLE, handle); +} + +PyDoc_STRVAR(CreatePipe_doc, +"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\ +\n\ +Create an anonymous pipe, and return handles to the read and\n\ +write ends of the pipe.\n\ +\n\ +pipe_attrs is ignored internally and can be None."); + +static PyObject * +winapi_CreatePipe(PyObject* self, PyObject* args) +{ + HANDLE read_pipe; + HANDLE write_pipe; + BOOL result; + + PyObject* pipe_attributes; /* ignored */ + DWORD size; + + if (! PyArg_ParseTuple(args, "O" F_DWORD ":CreatePipe", + &pipe_attributes, &size)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = CreatePipe(&read_pipe, &write_pipe, NULL, size); + Py_END_ALLOW_THREADS + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return Py_BuildValue( + "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe)); +} + +/* helpers for createprocess */ + +static unsigned long +getulong(PyObject* obj, char* name) +{ + PyObject* value; + unsigned long ret; + + value = PyObject_GetAttrString(obj, name); + if (! value) { + PyErr_Clear(); /* FIXME: propagate error? */ + return 0; + } + ret = PyLong_AsUnsignedLong(value); + Py_DECREF(value); + return ret; +} + +static HANDLE +gethandle(PyObject* obj, char* name) +{ + PyObject* value; + HANDLE ret; + + value = PyObject_GetAttrString(obj, name); + if (! value) { + PyErr_Clear(); /* FIXME: propagate error? */ + return NULL; + } + if (value == Py_None) + ret = NULL; + else + ret = PYNUM_TO_HANDLE(value); + Py_DECREF(value); + return ret; +} + +static PyObject* +getenvironment(PyObject* environment) +{ + Py_ssize_t i, envsize, totalsize; + Py_UCS4 *buffer = NULL, *p, *end; + PyObject *keys, *values, *res; + + /* convert environment dictionary to windows enviroment string */ + if (! PyMapping_Check(environment)) { + PyErr_SetString( + PyExc_TypeError, "environment must be dictionary or None"); + return NULL; + } + + envsize = PyMapping_Length(environment); + + keys = PyMapping_Keys(environment); + values = PyMapping_Values(environment); + if (!keys || !values) + goto error; + + totalsize = 1; /* trailing null character */ + for (i = 0; i < envsize; i++) { + PyObject* key = PyList_GET_ITEM(keys, i); + PyObject* value = PyList_GET_ITEM(values, i); + + if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "environment can only contain strings"); + goto error; + } + totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */ + totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */ + } + + buffer = PyMem_Malloc(totalsize * sizeof(Py_UCS4)); + if (! buffer) + goto error; + p = buffer; + end = buffer + totalsize; + + for (i = 0; i < envsize; i++) { + PyObject* key = PyList_GET_ITEM(keys, i); + PyObject* value = PyList_GET_ITEM(values, i); + if (!PyUnicode_AsUCS4(key, p, end - p, 0)) + goto error; + p += PyUnicode_GET_LENGTH(key); + *p++ = '='; + if (!PyUnicode_AsUCS4(value, p, end - p, 0)) + goto error; + p += PyUnicode_GET_LENGTH(value); + *p++ = '\0'; + } + + /* add trailing null byte */ + *p++ = '\0'; + assert(p == end); + + Py_XDECREF(keys); + Py_XDECREF(values); + + res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer); + PyMem_Free(buffer); + return res; + + error: + PyMem_Free(buffer); + Py_XDECREF(keys); + Py_XDECREF(values); + return NULL; +} + +PyDoc_STRVAR(CreateProcess_doc, +"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\ + inherit, flags, env_mapping, curdir,\n\ + startup_info) -> (proc_handle, thread_handle,\n\ + pid, tid)\n\ +\n\ +Create a new process and its primary thread. The return\n\ +value is a tuple of the process handle, thread handle,\n\ +process ID, and thread ID.\n\ +\n\ +proc_attrs and thread_attrs are ignored internally and can be None."); + +static PyObject * +winapi_CreateProcess(PyObject* self, PyObject* args) +{ + BOOL result; + PROCESS_INFORMATION pi; + STARTUPINFOW si; + PyObject* environment; + wchar_t *wenvironment; + + wchar_t* application_name; + wchar_t* command_line; + PyObject* process_attributes; /* ignored */ + PyObject* thread_attributes; /* ignored */ + BOOL inherit_handles; + DWORD creation_flags; + PyObject* env_mapping; + wchar_t* current_directory; + PyObject* startup_info; + + if (! PyArg_ParseTuple(args, "ZZOO" F_BOOL F_DWORD "OZO:CreateProcess", + &application_name, + &command_line, + &process_attributes, + &thread_attributes, + &inherit_handles, + &creation_flags, + &env_mapping, + ¤t_directory, + &startup_info)) + return NULL; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + /* note: we only support a small subset of all SI attributes */ + si.dwFlags = getulong(startup_info, "dwFlags"); + si.wShowWindow = (WORD)getulong(startup_info, "wShowWindow"); + si.hStdInput = gethandle(startup_info, "hStdInput"); + si.hStdOutput = gethandle(startup_info, "hStdOutput"); + si.hStdError = gethandle(startup_info, "hStdError"); + if (PyErr_Occurred()) + return NULL; + + if (env_mapping != Py_None) { + environment = getenvironment(env_mapping); + if (! environment) + return NULL; + wenvironment = PyUnicode_AsUnicode(environment); + if (wenvironment == NULL) + { + Py_XDECREF(environment); + return NULL; + } + } + else { + environment = NULL; + wenvironment = NULL; + } + + Py_BEGIN_ALLOW_THREADS + result = CreateProcessW(application_name, + command_line, + NULL, + NULL, + inherit_handles, + creation_flags | CREATE_UNICODE_ENVIRONMENT, + wenvironment, + current_directory, + &si, + &pi); + Py_END_ALLOW_THREADS + + Py_XDECREF(environment); + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return Py_BuildValue("NNkk", + HANDLE_TO_PYNUM(pi.hProcess), + HANDLE_TO_PYNUM(pi.hThread), + pi.dwProcessId, + pi.dwThreadId); +} + +PyDoc_STRVAR(DuplicateHandle_doc, +"DuplicateHandle(source_proc_handle, source_handle,\n\ + target_proc_handle, target_handle, access,\n\ + inherit[, options]) -> handle\n\ +\n\ +Return a duplicate handle object.\n\ +\n\ +The duplicate handle refers to the same object as the original\n\ +handle. Therefore, any changes to the object are reflected\n\ +through both handles."); + +static PyObject * +winapi_DuplicateHandle(PyObject* self, PyObject* args) +{ + HANDLE target_handle; + BOOL result; + + HANDLE source_process_handle; + HANDLE source_handle; + HANDLE target_process_handle; + DWORD desired_access; + BOOL inherit_handle; + DWORD options = 0; + + if (! PyArg_ParseTuple(args, + F_HANDLE F_HANDLE F_HANDLE F_DWORD F_BOOL F_DWORD + ":DuplicateHandle", + &source_process_handle, + &source_handle, + &target_process_handle, + &desired_access, + &inherit_handle, + &options)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = DuplicateHandle( + source_process_handle, + source_handle, + target_process_handle, + &target_handle, + desired_access, + inherit_handle, + options + ); + Py_END_ALLOW_THREADS + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return HANDLE_TO_PYNUM(target_handle); +} + +static PyObject * +winapi_ExitProcess(PyObject *self, PyObject *args) +{ + UINT uExitCode; + + if (!PyArg_ParseTuple(args, F_UINT, &uExitCode)) + return NULL; + + #if defined(Py_DEBUG) + SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT| + SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); + #endif + + ExitProcess(uExitCode); + + return NULL; +} + +PyDoc_STRVAR(GetCurrentProcess_doc, +"GetCurrentProcess() -> handle\n\ +\n\ +Return a handle object for the current process."); + +static PyObject * +winapi_GetCurrentProcess(PyObject* self, PyObject* args) +{ + if (! PyArg_ParseTuple(args, ":GetCurrentProcess")) + return NULL; + + return HANDLE_TO_PYNUM(GetCurrentProcess()); +} + +PyDoc_STRVAR(GetExitCodeProcess_doc, +"GetExitCodeProcess(handle) -> Exit code\n\ +\n\ +Return the termination status of the specified process."); + +static PyObject * +winapi_GetExitCodeProcess(PyObject* self, PyObject* args) +{ + DWORD exit_code; + BOOL result; + + HANDLE process; + if (! PyArg_ParseTuple(args, F_HANDLE ":GetExitCodeProcess", &process)) + return NULL; + + result = GetExitCodeProcess(process, &exit_code); + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return PyLong_FromUnsignedLong(exit_code); +} + +static PyObject * +winapi_GetLastError(PyObject *self, PyObject *args) +{ + return Py_BuildValue(F_DWORD, GetLastError()); +} + +PyDoc_STRVAR(GetModuleFileName_doc, +"GetModuleFileName(module) -> path\n\ +\n\ +Return the fully-qualified path for the file that contains\n\ +the specified module. The module must have been loaded by the\n\ +current process.\n\ +\n\ +The module parameter should be a handle to the loaded module\n\ +whose path is being requested. If this parameter is 0, \n\ +GetModuleFileName retrieves the path of the executable file\n\ +of the current process."); + +static PyObject * +winapi_GetModuleFileName(PyObject* self, PyObject* args) +{ + BOOL result; + HMODULE module; + WCHAR filename[MAX_PATH]; + + if (! PyArg_ParseTuple(args, F_HANDLE ":GetModuleFileName", + &module)) + return NULL; + + result = GetModuleFileNameW(module, filename, MAX_PATH); + filename[MAX_PATH-1] = '\0'; + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return PyUnicode_FromWideChar(filename, wcslen(filename)); +} + +PyDoc_STRVAR(GetStdHandle_doc, +"GetStdHandle(handle) -> integer\n\ +\n\ +Return a handle to the specified standard device\n\ +(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\ +The integer associated with the handle object is returned."); + +static PyObject * +winapi_GetStdHandle(PyObject* self, PyObject* args) +{ + HANDLE handle; + DWORD std_handle; + + if (! PyArg_ParseTuple(args, F_DWORD ":GetStdHandle", &std_handle)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + handle = GetStdHandle(std_handle); + Py_END_ALLOW_THREADS + + if (handle == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(GetLastError()); + + if (! handle) { + Py_INCREF(Py_None); + return Py_None; + } + + /* note: returns integer, not handle object */ + return HANDLE_TO_PYNUM(handle); +} + +PyDoc_STRVAR(GetVersion_doc, +"GetVersion() -> version\n\ +\n\ +Return the version number of the current operating system."); + +static PyObject * +winapi_GetVersion(PyObject* self, PyObject* args) +{ + if (! PyArg_ParseTuple(args, ":GetVersion")) + return NULL; + + return PyLong_FromUnsignedLong(GetVersion()); +} + +static PyObject * +winapi_OpenProcess(PyObject *self, PyObject *args) +{ + DWORD dwDesiredAccess; + BOOL bInheritHandle; + DWORD dwProcessId; + HANDLE handle; + + if (!PyArg_ParseTuple(args, F_DWORD F_BOOL F_DWORD, + &dwDesiredAccess, &bInheritHandle, &dwProcessId)) + return NULL; + + handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); + if (handle == NULL) + return PyErr_SetFromWindowsErr(0); + + return Py_BuildValue(F_HANDLE, handle); +} + +static PyObject * +winapi_PeekNamedPipe(PyObject *self, PyObject *args) +{ + HANDLE handle; + int size = 0; + PyObject *buf = NULL; + DWORD nread, navail, nleft; + BOOL ret; + + if (!PyArg_ParseTuple(args, F_HANDLE "|i:PeekNamedPipe" , &handle, &size)) + return NULL; + + if (size < 0) { + PyErr_SetString(PyExc_ValueError, "negative size"); + return NULL; + } + + if (size) { + buf = PyBytes_FromStringAndSize(NULL, size); + if (!buf) + return NULL; + Py_BEGIN_ALLOW_THREADS + ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread, + &navail, &nleft); + Py_END_ALLOW_THREADS + if (!ret) { + Py_DECREF(buf); + return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); + } + if (_PyBytes_Resize(&buf, nread)) + return NULL; + return Py_BuildValue("Nii", buf, navail, nleft); + } + else { + Py_BEGIN_ALLOW_THREADS + ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft); + Py_END_ALLOW_THREADS + if (!ret) { + return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); + } + return Py_BuildValue("ii", navail, nleft); + } +} + +static PyObject * +winapi_ReadFile(PyObject *self, PyObject *args, PyObject *kwds) +{ + HANDLE handle; + int size; + DWORD nread; + PyObject *buf; + BOOL ret; + int use_overlapped = 0; + DWORD err; + OverlappedObject *overlapped = NULL; + static char *kwlist[] = {"handle", "size", "overlapped", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, + F_HANDLE "i|i:ReadFile", kwlist, + &handle, &size, &use_overlapped)) + return NULL; + + buf = PyBytes_FromStringAndSize(NULL, size); + if (!buf) + return NULL; + if (use_overlapped) { + overlapped = new_overlapped(handle); + if (!overlapped) { + Py_DECREF(buf); + return NULL; + } + /* Steals reference to buf */ + overlapped->read_buffer = buf; + } + + Py_BEGIN_ALLOW_THREADS + ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread, + overlapped ? &overlapped->overlapped : NULL); + Py_END_ALLOW_THREADS + + err = ret ? 0 : GetLastError(); + + if (overlapped) { + if (!ret) { + if (err == ERROR_IO_PENDING) + overlapped->pending = 1; + else if (err != ERROR_MORE_DATA) { + Py_DECREF(overlapped); + return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); + } + } + return Py_BuildValue("NI", (PyObject *) overlapped, err); + } + + if (!ret && err != ERROR_MORE_DATA) { + Py_DECREF(buf); + return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); + } + if (_PyBytes_Resize(&buf, nread)) + return NULL; + return Py_BuildValue("NI", buf, err); +} + +static PyObject * +winapi_SetNamedPipeHandleState(PyObject *self, PyObject *args) +{ + HANDLE hNamedPipe; + PyObject *oArgs[3]; + DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL}; + int i; + + if (!PyArg_ParseTuple(args, F_HANDLE "OOO", + &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2])) + return NULL; + + PyErr_Clear(); + + for (i = 0 ; i < 3 ; i++) { + if (oArgs[i] != Py_None) { + dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]); + if (PyErr_Occurred()) + return NULL; + pArgs[i] = &dwArgs[i]; + } + } + + if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2])) + return PyErr_SetFromWindowsErr(0); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(TerminateProcess_doc, +"TerminateProcess(handle, exit_code) -> None\n\ +\n\ +Terminate the specified process and all of its threads."); + +static PyObject * +winapi_TerminateProcess(PyObject* self, PyObject* args) +{ + BOOL result; + + HANDLE process; + UINT exit_code; + if (! PyArg_ParseTuple(args, F_HANDLE F_UINT ":TerminateProcess", + &process, &exit_code)) + return NULL; + + result = TerminateProcess(process, exit_code); + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +winapi_WaitNamedPipe(PyObject *self, PyObject *args) +{ + LPCTSTR lpNamedPipeName; + DWORD nTimeOut; + BOOL success; + + if (!PyArg_ParseTuple(args, "s" F_DWORD, &lpNamedPipeName, &nTimeOut)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + success = WaitNamedPipe(lpNamedPipeName, nTimeOut); + Py_END_ALLOW_THREADS + + if (!success) + return PyErr_SetFromWindowsErr(0); + + Py_RETURN_NONE; +} + +static PyObject * +winapi_WaitForMultipleObjects(PyObject* self, PyObject* args) +{ + DWORD result; + PyObject *handle_seq; + HANDLE handles[MAXIMUM_WAIT_OBJECTS]; + HANDLE sigint_event = NULL; + Py_ssize_t nhandles, i; + BOOL wait_flag; + DWORD milliseconds = INFINITE; + + if (!PyArg_ParseTuple(args, "O" F_BOOL "|" F_DWORD + ":WaitForMultipleObjects", + &handle_seq, &wait_flag, &milliseconds)) + return NULL; + + if (!PySequence_Check(handle_seq)) { + PyErr_Format(PyExc_TypeError, + "sequence type expected, got '%s'", + Py_TYPE(handle_seq)->tp_doc); + return NULL; + } + nhandles = PySequence_Length(handle_seq); + if (nhandles == -1) + return NULL; + if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) { + PyErr_Format(PyExc_ValueError, + "need at most %zd handles, got a sequence of length %zd", + MAXIMUM_WAIT_OBJECTS - 1, nhandles); + return NULL; + } + for (i = 0; i < nhandles; i++) { + HANDLE h; + PyObject *v = PySequence_GetItem(handle_seq, i); + if (v == NULL) + return NULL; + if (!PyArg_Parse(v, F_HANDLE, &h)) { + Py_DECREF(v); + return NULL; + } + handles[i] = h; + Py_DECREF(v); + } + /* If this is the main thread then make the wait interruptible + by Ctrl-C unless we are waiting for *all* handles */ + if (!wait_flag && _PyOS_IsMainThread()) { + sigint_event = _PyOS_SigintEvent(); + assert(sigint_event != NULL); + handles[nhandles++] = sigint_event; + } + + Py_BEGIN_ALLOW_THREADS + if (sigint_event != NULL) + ResetEvent(sigint_event); + result = WaitForMultipleObjects((DWORD) nhandles, handles, + wait_flag, milliseconds); + Py_END_ALLOW_THREADS + + if (result == WAIT_FAILED) + return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); + else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) { + errno = EINTR; + return PyErr_SetFromErrno(PyExc_IOError); + } + + return PyLong_FromLong((int) result); +} + +PyDoc_STRVAR(WaitForSingleObject_doc, +"WaitForSingleObject(handle, timeout) -> result\n\ +\n\ +Wait until the specified object is in the signaled state or\n\ +the time-out interval elapses. The timeout value is specified\n\ +in milliseconds."); + +static PyObject * +winapi_WaitForSingleObject(PyObject* self, PyObject* args) +{ + DWORD result; + + HANDLE handle; + DWORD milliseconds; + if (! PyArg_ParseTuple(args, F_HANDLE F_DWORD ":WaitForSingleObject", + &handle, + &milliseconds)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = WaitForSingleObject(handle, milliseconds); + Py_END_ALLOW_THREADS + + if (result == WAIT_FAILED) + return PyErr_SetFromWindowsErr(GetLastError()); + + return PyLong_FromUnsignedLong(result); +} + +static PyObject * +winapi_WriteFile(PyObject *self, PyObject *args, PyObject *kwds) +{ + HANDLE handle; + Py_buffer _buf, *buf; + PyObject *bufobj; + DWORD written; + BOOL ret; + int use_overlapped = 0; + DWORD err; + OverlappedObject *overlapped = NULL; + static char *kwlist[] = {"handle", "buffer", "overlapped", NULL}; + + /* First get handle and use_overlapped to know which Py_buffer to use */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, + F_HANDLE "O|i:WriteFile", kwlist, + &handle, &bufobj, &use_overlapped)) + return NULL; + + if (use_overlapped) { + overlapped = new_overlapped(handle); + if (!overlapped) + return NULL; + buf = &overlapped->write_buffer; + } + else + buf = &_buf; + + if (!PyArg_Parse(bufobj, "y*", buf)) { + Py_XDECREF(overlapped); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + ret = WriteFile(handle, buf->buf, buf->len, &written, + overlapped ? &overlapped->overlapped : NULL); + Py_END_ALLOW_THREADS + + err = ret ? 0 : GetLastError(); + + if (overlapped) { + if (!ret) { + if (err == ERROR_IO_PENDING) + overlapped->pending = 1; + else { + Py_DECREF(overlapped); + return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); + } + } + return Py_BuildValue("NI", (PyObject *) overlapped, err); + } + + PyBuffer_Release(buf); + if (!ret) + return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); + return Py_BuildValue("II", written, err); +} + + +static PyMethodDef winapi_functions[] = { + {"CloseHandle", winapi_CloseHandle, METH_VARARGS, + CloseHandle_doc}, + {"ConnectNamedPipe", (PyCFunction)winapi_ConnectNamedPipe, + METH_VARARGS | METH_KEYWORDS, ""}, + {"CreateFile", winapi_CreateFile, METH_VARARGS, + ""}, + {"CreateNamedPipe", winapi_CreateNamedPipe, METH_VARARGS, + ""}, + {"CreatePipe", winapi_CreatePipe, METH_VARARGS, + CreatePipe_doc}, + {"CreateProcess", winapi_CreateProcess, METH_VARARGS, + CreateProcess_doc}, + {"DuplicateHandle", winapi_DuplicateHandle, METH_VARARGS, + DuplicateHandle_doc}, + {"ExitProcess", winapi_ExitProcess, METH_VARARGS, + ""}, + {"GetCurrentProcess", winapi_GetCurrentProcess, METH_VARARGS, + GetCurrentProcess_doc}, + {"GetExitCodeProcess", winapi_GetExitCodeProcess, METH_VARARGS, + GetExitCodeProcess_doc}, + {"GetLastError", winapi_GetLastError, METH_NOARGS, + GetCurrentProcess_doc}, + {"GetModuleFileName", winapi_GetModuleFileName, METH_VARARGS, + GetModuleFileName_doc}, + {"GetStdHandle", winapi_GetStdHandle, METH_VARARGS, + GetStdHandle_doc}, + {"GetVersion", winapi_GetVersion, METH_VARARGS, + GetVersion_doc}, + {"OpenProcess", winapi_OpenProcess, METH_VARARGS, + ""}, + {"PeekNamedPipe", winapi_PeekNamedPipe, METH_VARARGS, + ""}, + {"ReadFile", (PyCFunction)winapi_ReadFile, METH_VARARGS | METH_KEYWORDS, + ""}, + {"SetNamedPipeHandleState", winapi_SetNamedPipeHandleState, METH_VARARGS, + ""}, + {"TerminateProcess", winapi_TerminateProcess, METH_VARARGS, + TerminateProcess_doc}, + {"WaitNamedPipe", winapi_WaitNamedPipe, METH_VARARGS, + ""}, + {"WaitForMultipleObjects", winapi_WaitForMultipleObjects, METH_VARARGS, + ""}, + {"WaitForSingleObject", winapi_WaitForSingleObject, METH_VARARGS, + WaitForSingleObject_doc}, + {"WriteFile", (PyCFunction)winapi_WriteFile, METH_VARARGS | METH_KEYWORDS, + ""}, + {NULL, NULL} +}; + +static struct PyModuleDef winapi_module = { + PyModuleDef_HEAD_INIT, + "_winapi", + NULL, + -1, + winapi_functions, + NULL, + NULL, + NULL, + NULL +}; + +#define WINAPI_CONSTANT(fmt, con) \ + PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con)) + +PyMODINIT_FUNC +PyInit__winapi(void) +{ + PyObject *d; + PyObject *m; + + if (PyType_Ready(&OverlappedType) < 0) + return NULL; + + m = PyModule_Create(&winapi_module); + if (m == NULL) + return NULL; + d = PyModule_GetDict(m); + + PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType); + + /* constants */ + WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE); + WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP); + WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS); + WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS); + WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE); + WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); + WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA); + WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); + WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); + WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); + WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); + WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); + WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA); + WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); + WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); + WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED); + WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY); + WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED); + WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT); + WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE); + WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED); + WINAPI_CONSTANT(F_DWORD, GENERIC_READ); + WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE); + WINAPI_CONSTANT(F_DWORD, INFINITE); + WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER); + WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING); + WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX); + WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND); + WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE); + WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE); + WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES); + WINAPI_CONSTANT(F_DWORD, PIPE_WAIT); + WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS); + WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW); + WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES); + WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE); + WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE); + WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE); + WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE); + WINAPI_CONSTANT(F_DWORD, SW_HIDE); + WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0); + WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT); + + WINAPI_CONSTANT("i", NULL); + + return m; +} diff --git a/PC/_subprocess.c b/PC/_subprocess.c deleted file mode 100644 --- a/PC/_subprocess.c +++ /dev/null @@ -1,697 +0,0 @@ -/* - * support routines for subprocess module - * - * Currently, this extension module is only required when using the - * subprocess module on Windows, but in the future, stubs for other - * platforms might be added here as well. - * - * Copyright (c) 2004 by Fredrik Lundh - * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com - * Copyright (c) 2004 by Peter Astrand - * - * By obtaining, using, and/or copying this software and/or its - * associated documentation, you agree that you have read, understood, - * and will comply with the following terms and conditions: - * - * Permission to use, copy, modify, and distribute this software and - * its associated documentation for any purpose and without fee is - * hereby granted, provided that the above copyright notice appears in - * all copies, and that both that copyright notice and this permission - * notice appear in supporting documentation, and that the name of the - * authors not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. - * - * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* Licensed to PSF under a Contributor Agreement. */ -/* See http://www.python.org/2.4/license for licensing details. */ - -#include "Python.h" - -#define WINDOWS_LEAN_AND_MEAN -#include "windows.h" - -/* -------------------------------------------------------------------- */ -/* handle wrapper. note that this library uses integers when passing - handles to a function, and handle wrappers when returning handles. - the wrapper is used to provide Detach and Close methods */ - -typedef struct { - PyObject_HEAD - HANDLE handle; -} sp_handle_object; - -static PyTypeObject sp_handle_type; - -static PyObject* -sp_handle_new(HANDLE handle) -{ - sp_handle_object* self; - - self = PyObject_NEW(sp_handle_object, &sp_handle_type); - if (self == NULL) - return NULL; - - self->handle = handle; - - return (PyObject*) self; -} - -#if defined(MS_WIN32) && !defined(MS_WIN64) -#define HANDLE_TO_PYNUM(handle) PyLong_FromLong((long) handle) -#define PY_HANDLE_PARAM "l" -#else -#define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle) -#define PY_HANDLE_PARAM "L" -#endif - -static PyObject* -sp_handle_detach(sp_handle_object* self, PyObject* args) -{ - HANDLE handle; - - if (! PyArg_ParseTuple(args, ":Detach")) - return NULL; - - handle = self->handle; - - self->handle = INVALID_HANDLE_VALUE; - - /* note: return the current handle, as an integer */ - return HANDLE_TO_PYNUM(handle); -} - -static PyObject* -sp_handle_close(sp_handle_object* self, PyObject* args) -{ - if (! PyArg_ParseTuple(args, ":Close")) - return NULL; - - if (self->handle != INVALID_HANDLE_VALUE) { - CloseHandle(self->handle); - self->handle = INVALID_HANDLE_VALUE; - } - Py_INCREF(Py_None); - return Py_None; -} - -static void -sp_handle_dealloc(sp_handle_object* self) -{ - if (self->handle != INVALID_HANDLE_VALUE) - CloseHandle(self->handle); - PyObject_FREE(self); -} - -static PyMethodDef sp_handle_methods[] = { - {"Detach", (PyCFunction) sp_handle_detach, METH_VARARGS}, - {"Close", (PyCFunction) sp_handle_close, METH_VARARGS}, - {NULL, NULL} -}; - -static PyObject* -sp_handle_as_int(sp_handle_object* self) -{ - return HANDLE_TO_PYNUM(self->handle); -} - -static PyNumberMethods sp_handle_as_number; - -static PyTypeObject sp_handle_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_subprocess_handle", sizeof(sp_handle_object), 0, - (destructor) sp_handle_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - &sp_handle_as_number, /*tp_as_number */ - 0, /*tp_as_sequence */ - 0, /*tp_as_mapping */ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - sp_handle_methods, /*tp_methods*/ -}; - -/* -------------------------------------------------------------------- */ -/* windows API functions */ - -PyDoc_STRVAR(GetStdHandle_doc, -"GetStdHandle(handle) -> integer\n\ -\n\ -Return a handle to the specified standard device\n\ -(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\ -The integer associated with the handle object is returned."); - -static PyObject * -sp_GetStdHandle(PyObject* self, PyObject* args) -{ - HANDLE handle; - int std_handle; - - if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - handle = GetStdHandle((DWORD) std_handle); - Py_END_ALLOW_THREADS - - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(GetLastError()); - - if (! handle) { - Py_INCREF(Py_None); - return Py_None; - } - - /* note: returns integer, not handle object */ - return HANDLE_TO_PYNUM(handle); -} - -PyDoc_STRVAR(GetCurrentProcess_doc, -"GetCurrentProcess() -> handle\n\ -\n\ -Return a handle object for the current process."); - -static PyObject * -sp_GetCurrentProcess(PyObject* self, PyObject* args) -{ - if (! PyArg_ParseTuple(args, ":GetCurrentProcess")) - return NULL; - - return sp_handle_new(GetCurrentProcess()); -} - -PyDoc_STRVAR(DuplicateHandle_doc, -"DuplicateHandle(source_proc_handle, source_handle,\n\ - target_proc_handle, target_handle, access,\n\ - inherit[, options]) -> handle\n\ -\n\ -Return a duplicate handle object.\n\ -\n\ -The duplicate handle refers to the same object as the original\n\ -handle. Therefore, any changes to the object are reflected\n\ -through both handles."); - -static PyObject * -sp_DuplicateHandle(PyObject* self, PyObject* args) -{ - HANDLE target_handle; - BOOL result; - - HANDLE source_process_handle; - HANDLE source_handle; - HANDLE target_process_handle; - int desired_access; - int inherit_handle; - int options = 0; - - if (! PyArg_ParseTuple(args, - PY_HANDLE_PARAM PY_HANDLE_PARAM PY_HANDLE_PARAM - "ii|i:DuplicateHandle", - &source_process_handle, - &source_handle, - &target_process_handle, - &desired_access, - &inherit_handle, - &options)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - result = DuplicateHandle( - source_process_handle, - source_handle, - target_process_handle, - &target_handle, - desired_access, - inherit_handle, - options - ); - Py_END_ALLOW_THREADS - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return sp_handle_new(target_handle); -} - -PyDoc_STRVAR(CreatePipe_doc, -"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\ -\n\ -Create an anonymous pipe, and return handles to the read and\n\ -write ends of the pipe.\n\ -\n\ -pipe_attrs is ignored internally and can be None."); - -static PyObject * -sp_CreatePipe(PyObject* self, PyObject* args) -{ - HANDLE read_pipe; - HANDLE write_pipe; - BOOL result; - - PyObject* pipe_attributes; /* ignored */ - int size; - - if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - result = CreatePipe(&read_pipe, &write_pipe, NULL, size); - Py_END_ALLOW_THREADS - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return Py_BuildValue( - "NN", sp_handle_new(read_pipe), sp_handle_new(write_pipe)); -} - -/* helpers for createprocess */ - -static int -getint(PyObject* obj, char* name) -{ - PyObject* value; - int ret; - - value = PyObject_GetAttrString(obj, name); - if (! value) { - PyErr_Clear(); /* FIXME: propagate error? */ - return 0; - } - ret = (int) PyLong_AsLong(value); - Py_DECREF(value); - return ret; -} - -static HANDLE -gethandle(PyObject* obj, char* name) -{ - sp_handle_object* value; - HANDLE ret; - - value = (sp_handle_object*) PyObject_GetAttrString(obj, name); - if (! value) { - PyErr_Clear(); /* FIXME: propagate error? */ - return NULL; - } - if (Py_TYPE(value) != &sp_handle_type) - ret = NULL; - else - ret = value->handle; - Py_DECREF(value); - return ret; -} - -static PyObject* -getenvironment(PyObject* environment) -{ - Py_ssize_t i, envsize, totalsize; - Py_UCS4 *buffer = NULL, *p, *end; - PyObject *keys, *values, *res; - - /* convert environment dictionary to windows enviroment string */ - if (! PyMapping_Check(environment)) { - PyErr_SetString( - PyExc_TypeError, "environment must be dictionary or None"); - return NULL; - } - - envsize = PyMapping_Length(environment); - - keys = PyMapping_Keys(environment); - values = PyMapping_Values(environment); - if (!keys || !values) - goto error; - - totalsize = 1; /* trailing null character */ - for (i = 0; i < envsize; i++) { - PyObject* key = PyList_GET_ITEM(keys, i); - PyObject* value = PyList_GET_ITEM(values, i); - - if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "environment can only contain strings"); - goto error; - } - totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */ - totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */ - } - - buffer = PyMem_Malloc(totalsize * sizeof(Py_UCS4)); - if (! buffer) - goto error; - p = buffer; - end = buffer + totalsize; - - for (i = 0; i < envsize; i++) { - PyObject* key = PyList_GET_ITEM(keys, i); - PyObject* value = PyList_GET_ITEM(values, i); - if (!PyUnicode_AsUCS4(key, p, end - p, 0)) - goto error; - p += PyUnicode_GET_LENGTH(key); - *p++ = '='; - if (!PyUnicode_AsUCS4(value, p, end - p, 0)) - goto error; - p += PyUnicode_GET_LENGTH(value); - *p++ = '\0'; - } - - /* add trailing null byte */ - *p++ = '\0'; - assert(p == end); - - Py_XDECREF(keys); - Py_XDECREF(values); - - res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer); - PyMem_Free(buffer); - return res; - - error: - PyMem_Free(buffer); - Py_XDECREF(keys); - Py_XDECREF(values); - return NULL; -} - -PyDoc_STRVAR(CreateProcess_doc, -"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\ - inherit, flags, env_mapping, curdir,\n\ - startup_info) -> (proc_handle, thread_handle,\n\ - pid, tid)\n\ -\n\ -Create a new process and its primary thread. The return\n\ -value is a tuple of the process handle, thread handle,\n\ -process ID, and thread ID.\n\ -\n\ -proc_attrs and thread_attrs are ignored internally and can be None."); - -static PyObject * -sp_CreateProcess(PyObject* self, PyObject* args) -{ - BOOL result; - PROCESS_INFORMATION pi; - STARTUPINFOW si; - PyObject* environment; - wchar_t *wenvironment; - - wchar_t* application_name; - wchar_t* command_line; - PyObject* process_attributes; /* ignored */ - PyObject* thread_attributes; /* ignored */ - int inherit_handles; - int creation_flags; - PyObject* env_mapping; - wchar_t* current_directory; - PyObject* startup_info; - - if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess", - &application_name, - &command_line, - &process_attributes, - &thread_attributes, - &inherit_handles, - &creation_flags, - &env_mapping, - ¤t_directory, - &startup_info)) - return NULL; - - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - /* note: we only support a small subset of all SI attributes */ - si.dwFlags = getint(startup_info, "dwFlags"); - si.wShowWindow = getint(startup_info, "wShowWindow"); - si.hStdInput = gethandle(startup_info, "hStdInput"); - si.hStdOutput = gethandle(startup_info, "hStdOutput"); - si.hStdError = gethandle(startup_info, "hStdError"); - - if (PyErr_Occurred()) - return NULL; - - if (env_mapping != Py_None) { - environment = getenvironment(env_mapping); - if (! environment) - return NULL; - wenvironment = PyUnicode_AsUnicode(environment); - if (wenvironment == NULL) - { - Py_XDECREF(environment); - return NULL; - } - } - else { - environment = NULL; - wenvironment = NULL; - } - - Py_BEGIN_ALLOW_THREADS - result = CreateProcessW(application_name, - command_line, - NULL, - NULL, - inherit_handles, - creation_flags | CREATE_UNICODE_ENVIRONMENT, - wenvironment, - current_directory, - &si, - &pi); - Py_END_ALLOW_THREADS - - Py_XDECREF(environment); - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return Py_BuildValue("NNii", - sp_handle_new(pi.hProcess), - sp_handle_new(pi.hThread), - pi.dwProcessId, - pi.dwThreadId); -} - -PyDoc_STRVAR(TerminateProcess_doc, -"TerminateProcess(handle, exit_code) -> None\n\ -\n\ -Terminate the specified process and all of its threads."); - -static PyObject * -sp_TerminateProcess(PyObject* self, PyObject* args) -{ - BOOL result; - - HANDLE process; - int exit_code; - if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:TerminateProcess", - &process, &exit_code)) - return NULL; - - result = TerminateProcess(process, exit_code); - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(GetExitCodeProcess_doc, -"GetExitCodeProcess(handle) -> Exit code\n\ -\n\ -Return the termination status of the specified process."); - -static PyObject * -sp_GetExitCodeProcess(PyObject* self, PyObject* args) -{ - DWORD exit_code; - BOOL result; - - HANDLE process; - if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetExitCodeProcess", &process)) - return NULL; - - result = GetExitCodeProcess(process, &exit_code); - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return PyLong_FromLong(exit_code); -} - -PyDoc_STRVAR(WaitForSingleObject_doc, -"WaitForSingleObject(handle, timeout) -> result\n\ -\n\ -Wait until the specified object is in the signaled state or\n\ -the time-out interval elapses. The timeout value is specified\n\ -in milliseconds."); - -static PyObject * -sp_WaitForSingleObject(PyObject* self, PyObject* args) -{ - DWORD result; - - HANDLE handle; - int milliseconds; - if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:WaitForSingleObject", - &handle, - &milliseconds)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - result = WaitForSingleObject(handle, (DWORD) milliseconds); - Py_END_ALLOW_THREADS - - if (result == WAIT_FAILED) - return PyErr_SetFromWindowsErr(GetLastError()); - - return PyLong_FromLong((int) result); -} - -PyDoc_STRVAR(GetVersion_doc, -"GetVersion() -> version\n\ -\n\ -Return the version number of the current operating system."); - -static PyObject * -sp_GetVersion(PyObject* self, PyObject* args) -{ - if (! PyArg_ParseTuple(args, ":GetVersion")) - return NULL; - - return PyLong_FromLong((int) GetVersion()); -} - -PyDoc_STRVAR(GetModuleFileName_doc, -"GetModuleFileName(module) -> path\n\ -\n\ -Return the fully-qualified path for the file that contains\n\ -the specified module. The module must have been loaded by the\n\ -current process.\n\ -\n\ -The module parameter should be a handle to the loaded module\n\ -whose path is being requested. If this parameter is 0, \n\ -GetModuleFileName retrieves the path of the executable file\n\ -of the current process."); - -static PyObject * -sp_GetModuleFileName(PyObject* self, PyObject* args) -{ - BOOL result; - HMODULE module; - WCHAR filename[MAX_PATH]; - - if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetModuleFileName", - &module)) - return NULL; - - result = GetModuleFileNameW(module, filename, MAX_PATH); - filename[MAX_PATH-1] = '\0'; - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return PyUnicode_FromWideChar(filename, wcslen(filename)); -} - -static PyMethodDef sp_functions[] = { - {"GetStdHandle", sp_GetStdHandle, METH_VARARGS, GetStdHandle_doc}, - {"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS, - GetCurrentProcess_doc}, - {"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS, - DuplicateHandle_doc}, - {"CreatePipe", sp_CreatePipe, METH_VARARGS, CreatePipe_doc}, - {"CreateProcess", sp_CreateProcess, METH_VARARGS, CreateProcess_doc}, - {"TerminateProcess", sp_TerminateProcess, METH_VARARGS, - TerminateProcess_doc}, - {"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS, - GetExitCodeProcess_doc}, - {"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS, - WaitForSingleObject_doc}, - {"GetVersion", sp_GetVersion, METH_VARARGS, GetVersion_doc}, - {"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS, - GetModuleFileName_doc}, - {NULL, NULL} -}; - -/* -------------------------------------------------------------------- */ - -static void -defint(PyObject* d, const char* name, int value) -{ - PyObject* v = PyLong_FromLong((long) value); - if (v) { - PyDict_SetItemString(d, (char*) name, v); - Py_DECREF(v); - } -} - -static struct PyModuleDef _subprocessmodule = { - PyModuleDef_HEAD_INIT, - "_subprocess", - NULL, - -1, - sp_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__subprocess() -{ - PyObject *d; - PyObject *m; - - /* patch up object descriptors */ - sp_handle_as_number.nb_int = (unaryfunc) sp_handle_as_int; - if (PyType_Ready(&sp_handle_type) < 0) - return NULL; - - m = PyModule_Create(&_subprocessmodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); - - /* constants */ - defint(d, "STD_INPUT_HANDLE", STD_INPUT_HANDLE); - defint(d, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE); - defint(d, "STD_ERROR_HANDLE", STD_ERROR_HANDLE); - defint(d, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS); - defint(d, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES); - defint(d, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW); - defint(d, "SW_HIDE", SW_HIDE); - defint(d, "INFINITE", INFINITE); - defint(d, "WAIT_OBJECT_0", WAIT_OBJECT_0); - defint(d, "WAIT_TIMEOUT", WAIT_TIMEOUT); - defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE); - defint(d, "CREATE_NEW_PROCESS_GROUP", CREATE_NEW_PROCESS_GROUP); - defint(d, "STILL_ACTIVE", STILL_ACTIVE); - - return m; -} diff --git a/PC/config.c b/PC/config.c --- a/PC/config.c +++ b/PC/config.c @@ -56,7 +56,7 @@ extern PyObject* PyInit__codecs_jp(void); extern PyObject* PyInit__codecs_kr(void); extern PyObject* PyInit__codecs_tw(void); -extern PyObject* PyInit__subprocess(void); +extern PyObject* PyInit__winapi(void); extern PyObject* PyInit__lsprof(void); extern PyObject* PyInit__ast(void); extern PyObject* PyInit__io(void); @@ -101,8 +101,8 @@ {"msvcrt", PyInit_msvcrt}, {"_locale", PyInit__locale}, #endif - /* XXX Should _subprocess go in a WIN32 block? not WIN64? */ - {"_subprocess", PyInit__subprocess}, + /* XXX Should _winapi go in a WIN32 block? not WIN64? */ + {"_winapi", PyInit__winapi}, {"_codecs", PyInit__codecs}, {"_weakref", PyInit__weakref}, diff --git a/PCbuild/_multiprocessing.vcproj b/PCbuild/_multiprocessing.vcproj --- a/PCbuild/_multiprocessing.vcproj +++ b/PCbuild/_multiprocessing.vcproj @@ -534,10 +534,6 @@ RelativePath="..\Modules\_multiprocessing\semaphore.c" > - - diff --git a/PCbuild/pythoncore.vcproj b/PCbuild/pythoncore.vcproj --- a/PCbuild/pythoncore.vcproj +++ b/PCbuild/pythoncore.vcproj @@ -1055,6 +1055,10 @@ > + + @@ -1679,10 +1683,6 @@ Name="PC" > - - diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1387,7 +1387,6 @@ if platform == 'win32': multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c', '_multiprocessing/semaphore.c', - '_multiprocessing/win32_functions.c' ] else: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 21:26:02 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 21:26:02 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_don=27t_bother_keeping_a_se?= =?utf8?q?t_we=27ll_never_use?= Message-ID: http://hg.python.org/cpython/rev/052732bd3c10 changeset: 76406:052732bd3c10 user: Benjamin Peterson date: Wed Apr 18 15:25:50 2012 -0400 summary: don't bother keeping a set we'll never use files: Lib/importlib/_bootstrap.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -842,7 +842,8 @@ # We store two cached versions, to handle runtime changes of the # PYTHONCASEOK environment variable. self._path_cache = set(contents) - self._relaxed_path_cache = set(fn.lower() for fn in contents) + if sys.platform.startswith(CASE_INSENSITIVE_PLATFORMS): + self._relaxed_path_cache = set(fn.lower() for fn in contents) class _SourceFinderDetails: -- Repository URL: http://hg.python.org/cpython From martin at v.loewis.de Wed Apr 18 21:29:00 2012 From: martin at v.loewis.de (=?UTF-8?B?Ik1hcnRpbiB2LiBMw7Z3aXMi?=) Date: Wed, 18 Apr 2012 21:29:00 +0200 Subject: [Python-checkins] cpython: Issue #11750: The Windows API functions scattered in the _subprocess and In-Reply-To: References: Message-ID: <4F8F15FC.1010705@v.loewis.de> Am 18.04.2012 20:52, schrieb antoine.pitrou: > http://hg.python.org/cpython/rev/f3a27d11101a > changeset: 76405:f3a27d11101a > user: Antoine Pitrou > date: Wed Apr 18 20:51:15 2012 +0200 > summary: > Issue #11750: The Windows API functions scattered in the _subprocess and > _multiprocessing.win32 modules now live in a single module "_winapi". > Patch by sbt. Can we use Real Names, please? Regards, Martin From python-checkins at python.org Wed Apr 18 21:29:57 2012 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Apr 2012 21:29:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_update_importlib=2E=2E=2E?= Message-ID: http://hg.python.org/cpython/rev/474cf2dc500a changeset: 76407:474cf2dc500a user: Benjamin Peterson date: Wed Apr 18 15:29:52 2012 -0400 summary: update importlib... files: Python/importlib.h | Bin 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Python/importlib.h b/Python/importlib.h index 6279e00d5b1b2f405e6ff99b2234bf05321b10d7..3ccea93e3eec8e84972c009a5e59939e9a0d6aac GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 21:57:42 2012 From: python-checkins at python.org (ned.deily) Date: Wed, 18 Apr 2012 21:57:42 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Remove_webbrows?= =?utf8?q?er_doc_reference_to_the_previously_removed_internet-config?= Message-ID: http://hg.python.org/cpython/rev/dd23333b579a changeset: 76408:dd23333b579a branch: 2.7 parent: 76395:67be12ab8948 user: Ned Deily date: Wed Apr 18 12:48:09 2012 -0700 summary: Remove webbrowser doc reference to the previously removed internet-config option. files: Doc/library/webbrowser.rst | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -138,11 +138,9 @@ +-----------------------+-----------------------------------------+-------+ | ``'windows-default'`` | :class:`WindowsDefault` | \(2) | +-----------------------+-----------------------------------------+-------+ -| ``'internet-config'`` | :class:`InternetConfig` | \(3) | +| ``'macosx'`` | :class:`MacOSX('default')` | \(3) | +-----------------------+-----------------------------------------+-------+ -| ``'macosx'`` | :class:`MacOSX('default')` | \(4) | -+-----------------------+-----------------------------------------+-------+ -| ``'safari'`` | :class:`MacOSX('safari')` | \(4) | +| ``'safari'`` | :class:`MacOSX('safari')` | \(3) | +-----------------------+-----------------------------------------+-------+ Notes: @@ -158,9 +156,6 @@ Only on Windows platforms. (3) - Only on Mac OS platforms; requires the standard MacPython :mod:`ic` module. - -(4) Only on Mac OS X platform. Here are some simple examples:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 21:57:44 2012 From: python-checkins at python.org (ned.deily) Date: Wed, 18 Apr 2012 21:57:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Remove_webbrows?= =?utf8?q?er_doc_reference_to_the_previously_removed_internet-config?= Message-ID: http://hg.python.org/cpython/rev/292cbd59dbe0 changeset: 76409:292cbd59dbe0 branch: 3.2 parent: 76396:d368cc86dbc9 user: Ned Deily date: Wed Apr 18 12:48:52 2012 -0700 summary: Remove webbrowser doc reference to the previously removed internet-config option. files: Doc/library/webbrowser.rst | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -133,11 +133,9 @@ +-----------------------+-----------------------------------------+-------+ | ``'windows-default'`` | :class:`WindowsDefault` | \(2) | +-----------------------+-----------------------------------------+-------+ -| ``'internet-config'`` | :class:`InternetConfig` | \(3) | +| ``'macosx'`` | :class:`MacOSX('default')` | \(3) | +-----------------------+-----------------------------------------+-------+ -| ``'macosx'`` | :class:`MacOSX('default')` | \(4) | -+-----------------------+-----------------------------------------+-------+ -| ``'safari'`` | :class:`MacOSX('safari')` | \(4) | +| ``'safari'`` | :class:`MacOSX('safari')` | \(3) | +-----------------------+-----------------------------------------+-------+ Notes: @@ -153,9 +151,6 @@ Only on Windows platforms. (3) - Only on Mac OS platforms; requires the standard MacPython :mod:`ic` module. - -(4) Only on Mac OS X platform. Here are some simple examples:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 21:57:46 2012 From: python-checkins at python.org (ned.deily) Date: Wed, 18 Apr 2012 21:57:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Remove_webbrowser_doc_reference_to_the_previously_removed_in?= =?utf8?q?ternet-config?= Message-ID: http://hg.python.org/cpython/rev/b5e6cbacd6ab changeset: 76410:b5e6cbacd6ab parent: 76407:474cf2dc500a parent: 76409:292cbd59dbe0 user: Ned Deily date: Wed Apr 18 12:55:57 2012 -0700 summary: Remove webbrowser doc reference to the previously removed internet-config option. files: Doc/library/webbrowser.rst | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -133,11 +133,9 @@ +------------------------+-----------------------------------------+-------+ | ``'windows-default'`` | :class:`WindowsDefault` | \(2) | +------------------------+-----------------------------------------+-------+ -| ``'internet-config'`` | :class:`InternetConfig` | \(3) | +| ``'macosx'`` | :class:`MacOSX('default')` | \(3) | +------------------------+-----------------------------------------+-------+ -| ``'macosx'`` | :class:`MacOSX('default')` | \(4) | -+------------------------+-----------------------------------------+-------+ -| ``'safari'`` | :class:`MacOSX('safari')` | \(4) | +| ``'safari'`` | :class:`MacOSX('safari')` | \(3) | +------------------------+-----------------------------------------+-------+ | ``'google-chrome'`` | :class:`Chrome('google-chrome')` | | +------------------------+-----------------------------------------+-------+ @@ -161,9 +159,6 @@ Only on Windows platforms. (3) - Only on Mac OS platforms; requires the standard MacPython :mod:`ic` module. - -(4) Only on Mac OS X platform. .. versionadded:: 3.3 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 18 22:55:11 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 22:55:11 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_clock=5Fprecision?= =?utf8?q?=2Epy_was_wrong=2C_recompute_all_=22Precision_in_Python=22?= Message-ID: http://hg.python.org/peps/rev/5b2f298e0eed changeset: 4267:5b2f298e0eed user: Victor Stinner date: Wed Apr 18 22:49:58 2012 +0200 summary: PEP 418: clock_precision.py was wrong, recompute all "Precision in Python" files: pep-0418/clock_precision.py | 36 +++++++++++++++--------- 1 files changed, 22 insertions(+), 14 deletions(-) diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_precision.py --- a/pep-0418/clock_precision.py +++ b/pep-0418/clock_precision.py @@ -1,26 +1,33 @@ import time +try: + from time import timeout_time +except ImportError: + from time import time as timeout_time + def compute_precision(func): - previous = func() precision = None points = 0 - min_points = 100 - while points < min_points: - value = func() - if value == previous: - continue - dt = value - previous - previous = value + timeout = timeout_time() + 1.0 + previous = func() + while timeout_time() < timeout or points < 3: + for loop in range(10): + t1 = func() + t2 = func() + dt = t2 - t1 + if 0 < dt: + break + else: + dt = t2 - previous + if dt <= 0.0: + continue if precision is not None: precision = min(precision, dt) else: precision = dt - if precision < 10e-6: - min_points = 5000 - elif precision < 1e-3: - min_points = 1000 points += 1 - return dt + previous = func() + return precision def format_duration(dt): if dt >= 1e-3: @@ -31,8 +38,8 @@ return "%.0f ns" % (dt * 1e9) def test_clock(name, func): + print("%s:" % name) precision = compute_precision(func) - print("%s:" % name) print("- precision in Python: %s" % format_duration(precision)) @@ -50,6 +57,7 @@ print("- resolution: %s" % format_duration(info['resolution'])) clock_ids = [name for name in dir(time) if name.startswith("CLOCK_")] +clock_ids.sort() for clock_id_text in clock_ids: clock_id = getattr(time, clock_id_text) name = 'clock_gettime(%s)' % clock_id_text -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 18 23:59:03 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 18 Apr 2012 23:59:03 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Rerun_all_benchmark?= =?utf8?q?s_for_the_=22Precision_in_Python=22_column?= Message-ID: http://hg.python.org/peps/rev/1324cb0b94fc changeset: 4268:1324cb0b94fc user: Victor Stinner date: Wed Apr 18 23:59:02 2012 +0200 summary: PEP 418: Rerun all benchmarks for the "Precision in Python" column files: pep-0418.txt | 39 +++++++++++++++++++++------------------ 1 files changed, 21 insertions(+), 18 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -907,18 +907,18 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== -CLOCK_HIGHRES SunOS 5.11 2 ns 253 ns -CLOCK_MONOTONIC Linux 3.2 1 ns 2 ?s -CLOCK_MONOTONIC SunOS 5.11 2 ns 3 ?s -CLOCK_MONOTONIC_RAW Linux 3.2 1 ns 3 ?s -CLOCK_BOOTTIME Linux 3.3 1 ns 3 ?s +QueryPerformanceCounter Windows Seven 10 ns 10 ns +CLOCK_HIGHRES SunOS 5.11 2 ns 265 ns +CLOCK_MONOTONIC Linux 3.0 1 ns 322 ns +CLOCK_MONOTONIC_RAW Linux 3.3 1 ns 628 ns +CLOCK_BOOTTIME Linux 3.3 1 ns 628 ns mach_absolute_time() Mac OS 10.6 1 ns 3 ?s -CLOCK_MONOTONIC FreeBSD 8.2 11 ns 7 ?s -CLOCK_MONOTONIC OpenBSD 5.0 10 ms 7 ?s -QueryPerformanceCounter Windows Seven 10 ns 9 ?s -CLOCK_UPTIME FreeBSD 8.2 11 ns 9 ?s +CLOCK_MONOTONIC FreeBSD 8.2 11 ns 5 ?s +CLOCK_MONOTONIC OpenBSD 5.0 10 ms 5 ?s +CLOCK_UPTIME FreeBSD 8.2 11 ns 6 ?s CLOCK_MONOTONIC_COARSE Linux 3.3 1 ms 1 ms -GetTickCount64() Windows Seven 16 ms 16 ms +CLOCK_MONOTONIC_COARSE Linux 3.0 4 ms 4 ms +GetTickCount64() Windows Seven 16 ms 15 ms ========================= ================ ========= =================== mach_absolute_time @@ -1158,11 +1158,12 @@ Name Operating system Precision Precision in Python ========================= ================ ========= =================== CLOCK_REALTIME SunOS 5.11 10 ms 238 ns -CLOCK_REALTIME Linux 3.2 1 ns 2 ?s +CLOCK_REALTIME Linux 3.0 1 ns 238 ns gettimeofday() Mac OS 10.6 1 ?s 4 ?s -CLOCK_REALTIME FreeBSD 8.2 11 ns 7 ?s -CLOCK_REALTIME OpenBSD 5.0 10 ms 10 ?s +CLOCK_REALTIME FreeBSD 8.2 11 ns 6 ?s +CLOCK_REALTIME OpenBSD 5.0 10 ms 5 ?s CLOCK_REALTIME_COARSE Linux 3.3 1 ms 1 ms +CLOCK_REALTIME_COARSE Linux 3.0 4 ms 4 ms GetSystemTimeAsFileTime() Windows Seven 16 ms 1 ms ftime() Windows Seven \- 1 ms ========================= ================ ========= =================== @@ -1220,22 +1221,24 @@ ========================= ================ ========= =================== Name Operating system Precision Precision in Python ========================= ================ ========= =================== +CLOCK_PROCESS_CPUTIME_ID Linux 3.3 1 ns 1 ns CLOCK_PROF FreeBSD 8.2 10 ms 1 ?s getrusage(RUSAGE_SELF) FreeBSD 8.2 \- 1 ?s getrusage(RUSAGE_SELF) SunOS 5.11 \- 1 ?s -CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns 3 ?s +CLOCK_PROCESS_CPUTIME_ID Linux 3.0 1 ns 1 ?s getrusage(RUSAGE_SELF) Mac OS 10.6 \- 5 ?s clock() Mac OS 10.6 1 ?s 5 ?s -CLOCK_PROF OpenBSD 5.0 \- 7 ?s -getrusage(RUSAGE_SELF) Linux 3.3 \- 1 ms +CLOCK_PROF OpenBSD 5.0 \- 5 ?s +getrusage(RUSAGE_SELF) Linux 3.0 \- 4 ms getrusage(RUSAGE_SELF) OpenBSD 5.0 \- 8 ms clock() FreeBSD 8.2 8 ms 8 ms -clock() Linux 3.2 1 ?s 10 ms +clock() Linux 3.0 1 ?s 10 ms times() Linux 3.0 10 ms 10 ms clock() OpenBSD 5.0 10 ms 10 ms times() OpenBSD 5.0 10 ms 10 ms times() Mac OS 10.6 10 ms 10 ms clock() SunOS 5.11 1 ?s 10 ms +times() SunOS 5.11 1 ?s 10 ms GetProcessTimes() Windows Seven 16 ms 16 ms clock() Windows Seven 1 ms 1 ms ========================= ================ ========= =================== @@ -1290,7 +1293,7 @@ Name Operating system Precision Precision in Python ========================= ================ =============== =================== CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s 1 ?s -CLOCK_THREAD_CPUTIME_ID Linux 3.2 1 ns 6 ?s +CLOCK_THREAD_CPUTIME_ID Linux 3.3 1 ns 649 ns GetThreadTimes() Windows Seven 16 ms 16 ms ========================= ================ =============== =================== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 00:26:03 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 19 Apr 2012 00:26:03 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_comma?= Message-ID: http://hg.python.org/peps/rev/3f0af5cadb09 changeset: 4269:3f0af5cadb09 user: Benjamin Peterson date: Wed Apr 18 18:25:59 2012 -0400 summary: comma files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1,5 +1,5 @@ PEP: 418 -Title: Add monotonic time, performance counter and process time functions +Title: Add monotonic time, performance counter, and process time functions Version: $Revision$ Last-Modified: $Date$ Author: Cameron Simpson , Jim Jewett , Victor Stinner -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 01:00:19 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 19 Apr 2012 01:00:19 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314385=3A_Support_o?= =?utf8?q?ther_types_than_dict_for_=5F=5Fbuiltins=5F=5F?= Message-ID: http://hg.python.org/cpython/rev/e3ab8aa0216c changeset: 76411:e3ab8aa0216c user: Victor Stinner date: Thu Apr 19 00:57:45 2012 +0200 summary: Issue #14385: Support other types than dict for __builtins__ It is now possible to use a custom type for the __builtins__ namespace, instead of a dict. It can be used for sandboxing for example. Raise also a NameError instead of ImportError if __build_class__ name if not found in __builtins__. files: Lib/test/test_builtin.py | 33 ++++++ Misc/NEWS | 5 + Objects/frameobject.c | 6 +- Python/ceval.c | 144 +++++++++++++++++--------- 4 files changed, 135 insertions(+), 53 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -554,6 +554,39 @@ del l['__builtins__'] self.assertEqual((g, l), ({'a': 1}, {'b': 2})) + def test_exec_globals(self): + code = compile("print('Hello World!')", "", "exec") + # no builtin function + self.assertRaisesRegex(NameError, "name 'print' is not defined", + exec, code, {'__builtins__': {}}) + # __builtins__ must be a mapping type + self.assertRaises(TypeError, + exec, code, {'__builtins__': 123}) + + # no __build_class__ function + code = compile("class A: pass", "", "exec") + self.assertRaisesRegex(NameError, "__build_class__ not found", + exec, code, {'__builtins__': {}}) + + class frozendict_error(Exception): + pass + + class frozendict(dict): + def __setitem__(self, key, value): + raise frozendict_error("frozendict is readonly") + + # read-only builtins + frozen_builtins = frozendict(__builtins__) + code = compile("__builtins__['superglobal']=2; print(superglobal)", "test", "exec") + self.assertRaises(frozendict_error, + exec, code, {'__builtins__': frozen_builtins}) + + # read-only globals + namespace = frozendict({}) + code = compile("x=1", "test", "exec") + self.assertRaises(frozendict_error, + exec, code, namespace) + def test_exec_redirected(self): savestdout = sys.stdout sys.stdout = None # Whatever that cannot flush() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ Core and Builtins ----------------- +- Issue #14385: It is now possible to use a custom type for the __builtins__ + namespace, instead of a dict. It can be used for sandboxing for example. + Raise also a NameError instead of ImportError if __build_class__ name if not + found in __builtins__. + - Issue #12599: Be more strict in accepting None compared to a false-like object for importlib.util.module_for_loader and importlib.machinery.PathFinder. diff --git a/Objects/frameobject.c b/Objects/frameobject.c --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -614,10 +614,8 @@ if (builtins) { if (PyModule_Check(builtins)) { builtins = PyModule_GetDict(builtins); - assert(!builtins || PyDict_Check(builtins)); + assert(builtins != NULL); } - else if (!PyDict_Check(builtins)) - builtins = NULL; } if (builtins == NULL) { /* No builtins! Make up a minimal one @@ -636,7 +634,7 @@ /* If we share the globals, we share the builtins. Save a lookup and a call. */ builtins = back->f_builtins; - assert(builtins != NULL && PyDict_Check(builtins)); + assert(builtins != NULL); Py_INCREF(builtins); } if (code->co_zombieframe != NULL) { diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1932,11 +1932,26 @@ TARGET(LOAD_BUILD_CLASS) { _Py_IDENTIFIER(__build_class__); - x = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); - if (x == NULL) { - PyErr_SetString(PyExc_ImportError, - "__build_class__ not found"); - break; + + if (PyDict_CheckExact(f->f_builtins)) { + x = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); + if (x == NULL) { + PyErr_SetString(PyExc_NameError, + "__build_class__ not found"); + break; + } + } + else { + PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__); + if (build_class_str == NULL) + break; + x = PyObject_GetItem(f->f_builtins, build_class_str); + if (x == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) + PyErr_SetString(PyExc_NameError, + "__build_class__ not found"); + break; + } } Py_INCREF(x); PUSH(x); @@ -2078,12 +2093,24 @@ if (x == NULL) { x = PyDict_GetItem(f->f_globals, w); if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); - if (x == NULL) { - format_exc_check_arg( - PyExc_NameError, - NAME_ERROR_MSG, w); - break; + if (PyDict_CheckExact(f->f_builtins)) { + x = PyDict_GetItem(f->f_builtins, w); + if (x == NULL) { + format_exc_check_arg( + PyExc_NameError, + NAME_ERROR_MSG, w); + break; + } + } + else { + x = PyObject_GetItem(f->f_builtins, w); + if (x == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + NAME_ERROR_MSG, w); + break; + } } } Py_INCREF(x); @@ -2093,50 +2120,69 @@ TARGET(LOAD_GLOBAL) w = GETITEM(names, oparg); - if (PyUnicode_CheckExact(w)) { - /* Inline the PyDict_GetItem() calls. - WARNING: this is an extreme speed hack. - Do not try this at home. */ - Py_hash_t hash = ((PyASCIIObject *)w)->hash; - if (hash != -1) { - PyDictObject *d; - PyDictEntry *e; - d = (PyDictObject *)(f->f_globals); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; + if (PyDict_CheckExact(f->f_globals) + && PyDict_CheckExact(f->f_builtins)) { + if (PyUnicode_CheckExact(w)) { + /* Inline the PyDict_GetItem() calls. + WARNING: this is an extreme speed hack. + Do not try this at home. */ + Py_hash_t hash = ((PyASCIIObject *)w)->hash; + if (hash != -1) { + PyDictObject *d; + PyDictEntry *e; + d = (PyDictObject *)(f->f_globals); + e = d->ma_lookup(d, w, hash); + if (e == NULL) { + x = NULL; + break; + } + x = e->me_value; + if (x != NULL) { + Py_INCREF(x); + PUSH(x); + DISPATCH(); + } + d = (PyDictObject *)(f->f_builtins); + e = d->ma_lookup(d, w, hash); + if (e == NULL) { + x = NULL; + break; + } + x = e->me_value; + if (x != NULL) { + Py_INCREF(x); + PUSH(x); + DISPATCH(); + } + goto load_global_error; + } + } + /* This is the un-inlined version of the code above */ + x = PyDict_GetItem(f->f_globals, w); + if (x == NULL) { + x = PyDict_GetItem(f->f_builtins, w); + if (x == NULL) { + load_global_error: + format_exc_check_arg( + PyExc_NameError, + GLOBAL_NAME_ERROR_MSG, w); break; } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - d = (PyDictObject *)(f->f_builtins); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - goto load_global_error; } + Py_INCREF(x); + PUSH(x); + DISPATCH(); } - /* This is the un-inlined version of the code above */ - x = PyDict_GetItem(f->f_globals, w); + + /* Slow-path if globals or builtins is not a dict */ + x = PyObject_GetItem(f->f_globals, w); if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); + x = PyObject_GetItem(f->f_builtins, w); if (x == NULL) { - load_global_error: - format_exc_check_arg( - PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, w); + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + GLOBAL_NAME_ERROR_MSG, w); break; } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 19 01:12:51 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 19 Apr 2012 01:12:51 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Replace_definitions?= =?utf8?q?_of_Accuracy=2C_Precision_and_Resolution_in_the?= Message-ID: http://hg.python.org/peps/rev/1ea7a3edec42 changeset: 4270:1ea7a3edec42 user: Victor Stinner date: Thu Apr 19 01:12:50 2012 +0200 summary: PEP 418: Replace definitions of Accuracy, Precision and Resolution in the glossary with Stephen J. Turnbull's definitions files: pep-0418.txt | 17 +++++++---------- 1 files changed, 7 insertions(+), 10 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -2,7 +2,7 @@ Title: Add monotonic time, performance counter, and process time functions Version: $Revision$ Last-Modified: $Date$ -Author: Cameron Simpson , Jim Jewett , Victor Stinner +Author: Cameron Simpson , Jim Jewett , Stephen J. Turnbull , Victor Stinner Status: Draft Type: Standards Track Content-Type: text/x-rst @@ -569,9 +569,8 @@ ======== :Accuracy: - Is the answer correct? Any clock will eventually ; if a - clock is intended to match , it will need to be - back to the "true" time. See also `Accuracy and precision + The amount of deviation of measurements by a given instrument from + true values. See also `Accuracy and precision `_. :Adjusted: @@ -639,10 +638,8 @@ synchronization between cores. :Precision: - Significant Digits. What is the smallest duration that the clock - can distinguish? This differs from in that a - difference greater than the minimum precision is actually - meaningful. + The amount of deviation among measurements of the same physical + value by a single instrument. :Process Time: Time elapsed since the process began. It is typically measured in @@ -657,8 +654,8 @@ ambiguity; unfortunately, that introduces different ambiguities. :Resolution: - Represented Digits. Note that many clocks will have a resolution - greater than their actual . + The smallest difference between two physical values that results + in a different measurement by a given instrument. :Slew: A slight change to a clock's speed, usually intended to correct -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 01:28:22 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 19 Apr 2012 01:28:22 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Add_link_to_benchma?= =?utf8?q?rking_programs_used_to_fill_tables?= Message-ID: http://hg.python.org/peps/rev/22ce683f1a34 changeset: 4271:22ce683f1a34 user: Victor Stinner date: Thu Apr 19 01:28:22 2012 +0200 summary: PEP 418: Add link to benchmarking programs used to fill tables files: pep-0418.txt | 32 ++++++++++++++++++++++++-------- 1 files changed, 24 insertions(+), 8 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -800,7 +800,9 @@ Reading an hardware clock has a cost. The following table compares the performance of different hardware clocks on Linux 3.3 with Intel -Core i7-2600 at 3.40GHz (8 cores). +Core i7-2600 at 3.40GHz (8 cores). The `bench_time.c +`_ program +was used to fill these tables. ======================== ====== ======= ====== Function TSC ACPI PM HPET @@ -817,10 +819,6 @@ CLOCK_MONOTONIC 27 ns 723 ns 635 ns ======================== ====== ======= ====== -Each function was called 10,000,000 times and CLOCK_MONOTONIC was used -to get the time before and after. The benchmark was run 5 times to -keep the minimum time. - FreeBSD 8.0 in kvm with hardware virtualization: ======================== ====== ========= ======= ======= @@ -918,6 +916,11 @@ GetTickCount64() Windows Seven 16 ms 15 ms ========================= ================ ========= =================== +The "Precision in Python" column was filled using the +`clock_precision.py +`_ +program. + mach_absolute_time ^^^^^^^^^^^^^^^^^^ @@ -1165,6 +1168,11 @@ ftime() Windows Seven \- 1 ms ========================= ================ ========= =================== +The "Precision in Python" column was filled using the +`clock_precision.py +`_ +program. + Windows: GetSystemTimeAsFileTime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1240,6 +1248,11 @@ clock() Windows Seven 1 ms 1 ms ========================= ================ ========= =================== +The "Precision in Python" column was filled using the +`clock_precision.py +`_ +program. + Functions ^^^^^^^^^ @@ -1294,8 +1307,10 @@ GetThreadTimes() Windows Seven 16 ms 16 ms ========================= ================ =============== =================== -CLOCK_THREAD_CPUTIME_ID returns a number of CPU cycles, not a number of -seconds. +The "Precision in Python" column was filled using the +`clock_precision.py +`_ +program. Functions @@ -1305,7 +1320,8 @@ `_. The precision can be read using GetSystemTimeAdjustment(). * clock_gettime(CLOCK_THREAD_CPUTIME_ID): Thread-specific CPU-time - clock. The precision can be read using of clock_getres(). + clock. It uses a number of CPU cycles, not a number of seconds. + The precision can be read using of clock_getres(). See also the `QueryThreadCycleTime() function `_ -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 01:41:36 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 19 Apr 2012 01:41:36 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Fix_bench=5Ftime=2E?= =?utf8?q?c?= Message-ID: http://hg.python.org/peps/rev/d9b5b9470505 changeset: 4272:d9b5b9470505 user: Victor Stinner date: Thu Apr 19 01:41:35 2012 +0200 summary: PEP 418: Fix bench_time.c It may not affect the result because the benchmark is run 5 times files: pep-0418/bench_time.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/pep-0418/bench_time.c b/pep-0418/bench_time.c --- a/pep-0418/bench_time.c +++ b/pep-0418/bench_time.c @@ -131,8 +131,7 @@ dt += (after.tv_nsec - before.tv_nsec) * 1e-9; else { - dt -= 1.0; - dt += (before.tv_nsec - after.tv_nsec) * 1e-9; + dt -= (before.tv_nsec - after.tv_nsec) * 1e-9; } dt *= (double)1e9 / NLOOP / NUNROLL; -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 01:42:18 2012 From: python-checkins at python.org (gregory.p.smith) Date: Thu, 19 Apr 2012 01:42:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Fix_compiler_wa?= =?utf8?q?rning_related_to_issue_=2314331=2E__harmless=2E?= Message-ID: http://hg.python.org/cpython/rev/b82a471d2c5e changeset: 76412:b82a471d2c5e branch: 2.7 parent: 76408:dd23333b579a user: Gregory P. Smith date: Wed Apr 18 16:41:56 2012 -0700 summary: Fix compiler warning related to issue #14331. harmless. files: Python/import.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1267,7 +1267,8 @@ } name = PyMem_MALLOC(MAXPATHLEN+1); if (name == NULL) { - return PyErr_NoMemory(); + PyErr_NoMemory(); + return NULL; } strcpy(name, subname); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 19 02:48:10 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 19 Apr 2012 02:48:10 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Minor_updates?= Message-ID: http://hg.python.org/peps/rev/02b5d0d2ba55 changeset: 4273:02b5d0d2ba55 user: Victor Stinner date: Thu Apr 19 02:47:52 2012 +0200 summary: PEP 418: Minor updates files: pep-0418.txt | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -38,8 +38,8 @@ To measure CPU time, Python does not provide directly a portable function. ``time.clock()`` can be used on Unix, but it has a bad -precision. ``resource.getrusage()`` can also be used on Unix, but it -requires to get fields of a structure and compute the sum of time +precision. ``resource.getrusage()`` or ``os.times()`` can also be +used on Unix, but they requires to compute the sum of time spent in kernel space and user space. The new ``time.process_time()`` function acts as a portable counter that always measures CPU time (doesn't include time elapsed during sleep) and has the best available @@ -127,14 +127,14 @@ Windows and on other operating systems, ``time.monotonic()`` is system-wide. -Availability: Windows, Mac OS X, Unix, Solaris. Not available on -GNU/Hurd. +Availability: Windows, Mac OS X, Linux, FreeBSD, OpenBSD, Solaris. +Not available on GNU/Hurd. Pseudo-code [#pseudo]_:: if os.name == 'nt': # GetTickCount64() requires Windows Vista, Server 2008 or later - if hasattr(_time, '_GetTickCount64'): + if hasattr(_time, 'GetTickCount64'): def monotonic(): return _time.GetTickCount64() * 1e-3 else: @@ -174,7 +174,7 @@ ^^^^^^^^^^^^^^^^^^^ Performance counter with the highest available precision to measure a -duration. It does include time elapsed during sleep and is +short duration. It does include time elapsed during sleep and is system-wide. The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid and is a number of seconds. @@ -225,8 +225,8 @@ if os.name == 'nt': def process_time(): - handle = win32process.GetCurrentProcess() - process_times = win32process.GetProcessTimes(handle) + handle = _time.GetCurrentProcess() + process_times = _time.GetProcessTimes(handle) return (process_times['UserTime'] + process_times['KernelTime']) * 1e-7 else: try: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 02:48:57 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 19 Apr 2012 02:48:57 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_typo?= Message-ID: http://hg.python.org/peps/rev/adc5c6bc9ca2 changeset: 4274:adc5c6bc9ca2 user: Victor Stinner date: Thu Apr 19 02:48:56 2012 +0200 summary: PEP 418: typo files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -39,7 +39,7 @@ To measure CPU time, Python does not provide directly a portable function. ``time.clock()`` can be used on Unix, but it has a bad precision. ``resource.getrusage()`` or ``os.times()`` can also be -used on Unix, but they requires to compute the sum of time +used on Unix, but they require to compute the sum of time spent in kernel space and user space. The new ``time.process_time()`` function acts as a portable counter that always measures CPU time (doesn't include time elapsed during sleep) and has the best available -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 03:36:29 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 19 Apr 2012 03:36:29 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0NTM4OiBIVE1M?= =?utf8?q?Parser_can_now_parse_correctly_start_tags_that_contain_a_bare_/?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/36c901fcfcda changeset: 76413:36c901fcfcda branch: 2.7 user: Ezio Melotti date: Wed Apr 18 19:08:41 2012 -0600 summary: #14538: HTMLParser can now parse correctly start tags that contain a bare /. files: Lib/HTMLParser.py | 6 +++--- Lib/test/test_htmlparser.py | 10 ++++++++++ Misc/NEWS | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/HTMLParser.py b/Lib/HTMLParser.py --- a/Lib/HTMLParser.py +++ b/Lib/HTMLParser.py @@ -22,13 +22,13 @@ starttagopen = re.compile('<[a-zA-Z]') piclose = re.compile('>') commentclose = re.compile(r'--\s*>') -tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*') +tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*') # see http://www.w3.org/TR/html5/tokenization.html#tag-open-state # and http://www.w3.org/TR/html5/tokenization.html#tag-name-state tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*') attrfind = re.compile( - r'[\s/]*((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' + r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*') locatestarttagend = re.compile(r""" @@ -289,7 +289,7 @@ match = tagfind.match(rawdata, i+1) assert match, 'unexpected call to parse_starttag()' k = match.end() - self.lasttag = tag = rawdata[i+1:k].lower() + self.lasttag = tag = match.group(1).lower() while k < endpos: m = attrfind.match(rawdata, k) diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -260,6 +260,16 @@ ('starttag', 'a', [('foo', None), ('=', None), ('bar', None)]) ] self._run_check(html, expected) + #see issue #14538 + html = ('' + '') + expected = [ + ('starttag', 'meta', []), ('starttag', 'meta', []), + ('starttag', 'meta', []), ('starttag', 'meta', []), + ('startendtag', 'meta', []), ('startendtag', 'meta', []), + ('startendtag', 'meta', []), ('startendtag', 'meta', []), + ] + self._run_check(html, expected) def test_declaration_junk_chars(self): self._run_check("", [('decl', 'DOCTYPE foo $ ')]) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Library ------- +- Issue #14538: HTMLParser can now parse correctly start tags that contain + a bare '/'. + - Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. - Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 19 03:36:30 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 19 Apr 2012 03:36:30 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NTM4OiBIVE1M?= =?utf8?q?Parser_can_now_parse_correctly_start_tags_that_contain_a_bare_/?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/ba4baaddac8d changeset: 76414:ba4baaddac8d branch: 3.2 parent: 76409:292cbd59dbe0 user: Ezio Melotti date: Wed Apr 18 19:18:22 2012 -0600 summary: #14538: HTMLParser can now parse correctly start tags that contain a bare /. files: Lib/html/parser.py | 6 +++--- Lib/test/test_htmlparser.py | 10 ++++++++++ Misc/NEWS | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/html/parser.py b/Lib/html/parser.py --- a/Lib/html/parser.py +++ b/Lib/html/parser.py @@ -22,7 +22,7 @@ starttagopen = re.compile('<[a-zA-Z]') piclose = re.compile('>') commentclose = re.compile(r'--\s*>') -tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*') +tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*') # see http://www.w3.org/TR/html5/tokenization.html#tag-open-state # and http://www.w3.org/TR/html5/tokenization.html#tag-name-state tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*') @@ -36,7 +36,7 @@ r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*' r'(\'[^\']*\'|"[^"]*"|[^\s"\'=<>`]*))?') attrfind_tolerant = re.compile( - r'[\s/]*((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' + r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*') locatestarttagend = re.compile(r""" <[a-zA-Z][-.a-zA-Z0-9:_]* # tag name @@ -327,7 +327,7 @@ match = tagfind.match(rawdata, i+1) assert match, 'unexpected call to parse_starttag()' k = match.end() - self.lasttag = tag = rawdata[i+1:k].lower() + self.lasttag = tag = match.group(1).lower() while k < endpos: if self.strict: m = attrfind.match(rawdata, k) diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -409,6 +409,16 @@ ('starttag', 'a', [('foo', None), ('=', None), ('bar', None)]) ] self._run_check(html, expected) + #see issue #14538 + html = ('' + '') + expected = [ + ('starttag', 'meta', []), ('starttag', 'meta', []), + ('starttag', 'meta', []), ('starttag', 'meta', []), + ('startendtag', 'meta', []), ('startendtag', 'meta', []), + ('startendtag', 'meta', []), ('startendtag', 'meta', []), + ] + self._run_check(html, expected) def test_declaration_junk_chars(self): self._run_check("", [('decl', 'DOCTYPE foo $ ')]) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,9 @@ Library ------- +- Issue #14538: HTMLParser can now parse correctly start tags that contain + a bare '/'. + - Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. - Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 19 03:36:33 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 19 Apr 2012 03:36:33 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314538=3A_merge_with_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/0f837071fd97 changeset: 76415:0f837071fd97 parent: 76411:e3ab8aa0216c parent: 76414:ba4baaddac8d user: Ezio Melotti date: Wed Apr 18 19:36:03 2012 -0600 summary: #14538: merge with 3.2. files: Lib/html/parser.py | 6 +++--- Lib/test/test_htmlparser.py | 10 ++++++++++ Misc/NEWS | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/html/parser.py b/Lib/html/parser.py --- a/Lib/html/parser.py +++ b/Lib/html/parser.py @@ -22,7 +22,7 @@ starttagopen = re.compile('<[a-zA-Z]') piclose = re.compile('>') commentclose = re.compile(r'--\s*>') -tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*') +tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*') # see http://www.w3.org/TR/html5/tokenization.html#tag-open-state # and http://www.w3.org/TR/html5/tokenization.html#tag-name-state tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*') @@ -36,7 +36,7 @@ r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*' r'(\'[^\']*\'|"[^"]*"|[^\s"\'=<>`]*))?') attrfind_tolerant = re.compile( - r'[\s/]*((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' + r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*') locatestarttagend = re.compile(r""" <[a-zA-Z][-.a-zA-Z0-9:_]* # tag name @@ -327,7 +327,7 @@ match = tagfind.match(rawdata, i+1) assert match, 'unexpected call to parse_starttag()' k = match.end() - self.lasttag = tag = rawdata[i+1:k].lower() + self.lasttag = tag = match.group(1).lower() while k < endpos: if self.strict: m = attrfind.match(rawdata, k) diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -409,6 +409,16 @@ ('starttag', 'a', [('foo', None), ('=', None), ('bar', None)]) ] self._run_check(html, expected) + #see issue #14538 + html = ('' + '') + expected = [ + ('starttag', 'meta', []), ('starttag', 'meta', []), + ('starttag', 'meta', []), ('starttag', 'meta', []), + ('startendtag', 'meta', []), ('startendtag', 'meta', []), + ('startendtag', 'meta', []), ('startendtag', 'meta', []), + ] + self._run_check(html, expected) def test_declaration_junk_chars(self): self._run_check("", [('decl', 'DOCTYPE foo $ ')]) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -58,6 +58,9 @@ - Issue #14087: multiprocessing: add Condition.wait_for(). Patch by sbt. +- Issue #14538: HTMLParser can now parse correctly start tags that contain + a bare '/'. + - Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. - Issue #14386: Expose the dict_proxy internal type as types.MappingProxyType. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Apr 19 05:34:19 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 19 Apr 2012 05:34:19 +0200 Subject: [Python-checkins] Daily reference leaks (e3ab8aa0216c): sum=6 Message-ID: results for e3ab8aa0216c on branch "default" -------------------------------------------- test_tempfile leaked [2, 2, 2] references, sum=6 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogc0oQtT', '-x'] From python-checkins at python.org Thu Apr 19 10:32:54 2012 From: python-checkins at python.org (martin.v.loewis) Date: Thu, 19 Apr 2012 10:32:54 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Configure_docutils_to_use_hg_a?= =?utf8?q?s_CVS=2E?= Message-ID: http://hg.python.org/peps/rev/34076bfed420 changeset: 4275:34076bfed420 user: Martin v. L?wis date: Thu Apr 19 10:32:50 2012 +0200 summary: Configure docutils to use hg as CVS. files: pep2pyramid.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/pep2pyramid.py b/pep2pyramid.py --- a/pep2pyramid.py +++ b/pep2pyramid.py @@ -306,6 +306,8 @@ def fix_rst_pep(inpath, input_lines, outfile): from docutils import core + from docutils.transforms.peps import Headers + Headers.pep_cvs_url = PEPCVSURL parts = core.publish_parts( source=''.join(input_lines), source_path=inpath, -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 11:34:29 2012 From: python-checkins at python.org (martin.v.loewis) Date: Thu, 19 Apr 2012 11:34:29 +0200 (CEST) Subject: [Python-checkins] r88949 - tracker/instances/python-dev/html/issue.search.html Message-ID: <3VYFQY2NJvzN0B@mail.python.org> Author: martin.v.loewis Date: Thu Apr 19 11:34:28 2012 New Revision: 88949 Log: Issue 459: Link to date search documentation. Modified: tracker/instances/python-dev/html/issue.search.html Modified: tracker/instances/python-dev/html/issue.search.html ============================================================================== --- tracker/instances/python-dev/html/issue.search.html (original) +++ tracker/instances/python-dev/html/issue.search.html Thu Apr 19 11:34:28 2012 @@ -81,7 +81,7 @@ - Creation Date: + Creation Date: @@ -102,7 +102,7 @@ - Activity: + Activity: From python-checkins at python.org Thu Apr 19 14:23:14 2012 From: python-checkins at python.org (nick.coghlan) Date: Thu, 19 Apr 2012 14:23:14 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogQ2xvc2UgIzE0MDMy?= =?utf8?q?=3A_fix_incorrect_variable_reference_in_test=5Fcmd=5Fline=5Fscri?= =?utf8?q?pt?= Message-ID: http://hg.python.org/cpython/rev/c4c67c2d8ffc changeset: 76416:c4c67c2d8ffc branch: 3.2 parent: 76414:ba4baaddac8d user: Nick Coghlan date: Thu Apr 19 22:19:36 2012 +1000 summary: Close #14032: fix incorrect variable reference in test_cmd_line_script files: Lib/test/test_cmd_line_script.py | 2 +- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -242,7 +242,7 @@ script_name = _make_test_script(pkg_dir, 'script') rc, out, err = assert_python_ok('-m', 'test_pkg.script') if verbose > 1: - print(data) + print(out) expected = "init_argv0==%r" % '-m' self.assertIn(expected.encode('utf-8'), out) self._check_output(script_name, rc, out, diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1026,6 +1026,7 @@ Florent Xicluna Hirokazu Yamamoto Ka-Ping Yee +Jason Yeo Bob Yodlowski Danny Yoo George Yoshida diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -152,6 +152,9 @@ Tests ----- +- Issue #14032: Fix incorrect variable name in test_cmd_line_script debugging + message (Patch by Jason Yeo) + - Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing a test failure in test_ssl. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 19 14:23:14 2012 From: python-checkins at python.org (nick.coghlan) Date: Thu, 19 Apr 2012 14:23:14 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_from_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/18abb0b338c8 changeset: 76417:18abb0b338c8 parent: 76415:0f837071fd97 parent: 76416:c4c67c2d8ffc user: Nick Coghlan date: Thu Apr 19 22:22:37 2012 +1000 summary: Merge from 3.2 files: Lib/test/test_cmd_line_script.py | 2 +- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -242,7 +242,7 @@ script_name = _make_test_script(pkg_dir, 'script') rc, out, err = assert_python_ok('-m', 'test_pkg.script') if verbose > 1: - print(data) + print(out) expected = "init_argv0==%r" % '-m' self.assertIn(expected.encode('utf-8'), out) self._check_output(script_name, rc, out, diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1123,6 +1123,7 @@ Florent Xicluna Hirokazu Yamamoto Ka-Ping Yee +Jason Yeo Bob Yodlowski Danny Yoo George Yoshida diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -121,6 +121,9 @@ Tests ----- +- Issue #14032: Fix incorrect variable name in test_cmd_line_script debugging + message (Patch by Jason Yeo) + - Issue #14589: Update certificate chain for sha256.tbs-internet.com, fixing a test failure in test_ssl. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 19 14:34:23 2012 From: python-checkins at python.org (martin.v.loewis) Date: Thu, 19 Apr 2012 14:34:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314098=3A_New_funct?= =?utf8?q?ions_PyErr=5FGetExcInfo_and_PyErr=5FSetExcInfo=2E?= Message-ID: http://hg.python.org/cpython/rev/9fdec1354af4 changeset: 76418:9fdec1354af4 user: Martin v. L?wis date: Thu Apr 19 14:33:43 2012 +0200 summary: Issue #14098: New functions PyErr_GetExcInfo and PyErr_SetExcInfo. Patch by Stefan Behnel. files: Doc/c-api/exceptions.rst | 35 +++++++++++++++++++++++++++ Include/pyerrors.h | 2 + Lib/test/test_capi.py | 23 +++++++++++++++++ Misc/NEWS | 3 ++ Modules/_testcapimodule.c | 24 ++++++++++++++++++ Python/errors.c | 33 +++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 0 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -129,6 +129,41 @@ exception state. +.. c:function:: void PyErr_GetExcInfo(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback) + + Retrieve the exception info, as known from ``sys.exc_info()``. This refers + to an exception that was already caught, not to an exception that was + freshly raised. Returns new references for the three objects, any of which + may be *NULL*. Does not modify the exception info state. + + .. note:: + + This function is not normally used by code that wants to handle exceptions. + Rather, it can be used when code needs to save and restore the exception + state temporarily. Use :c:func:`PyErr_SetExcInfo` to restore or clear the + exception state. + +.. versionadded:: 3.3 + + +.. c:function:: void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) + + Set the exception info, as known from ``sys.exc_info()``. This refers + to an exception that was already caught, not to an exception that was + freshly raised. This function steals the references of the arguments. + To clear the exception state, pass *NULL* for all three arguments. + For general rules about the three arguments, see :c:func:`PyErr_Restore`. + + .. note:: + + This function is not normally used by code that wants to handle exceptions. + Rather, it can be used when code needs to save and restore the exception + state temporarily. Use :c:func:`PyErr_GetExcInfo` to read the exception + state. + +.. versionadded:: 3.3 + + .. c:function:: void PyErr_SetString(PyObject *type, const char *message) This is the most common way to set the error indicator. The first argument diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -82,6 +82,8 @@ PyAPI_FUNC(void) PyErr_Clear(void); PyAPI_FUNC(void) PyErr_Fetch(PyObject **, PyObject **, PyObject **); PyAPI_FUNC(void) PyErr_Restore(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(void) PyErr_GetExcInfo(PyObject **, PyObject **, PyObject **); +PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *); #if defined(__clang__) || \ (defined(__GNUC__) && \ diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -55,6 +55,29 @@ def test_memoryview_from_NULL_pointer(self): self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer) + def test_exc_info(self): + raised_exception = ValueError("5") + new_exc = TypeError("TEST") + try: + raise raised_exception + except ValueError as e: + tb = e.__traceback__ + orig_sys_exc_info = sys.exc_info() + orig_exc_info = _testcapi.set_exc_info(new_exc.__class__, new_exc, None) + new_sys_exc_info = sys.exc_info() + new_exc_info = _testcapi.set_exc_info(*orig_exc_info) + reset_sys_exc_info = sys.exc_info() + + self.assertEqual(orig_exc_info[1], e) + + self.assertSequenceEqual(orig_exc_info, (raised_exception.__class__, raised_exception, tb)) + self.assertSequenceEqual(orig_sys_exc_info, orig_exc_info) + self.assertSequenceEqual(reset_sys_exc_info, orig_exc_info) + self.assertSequenceEqual(new_exc_info, (new_exc.__class__, new_exc, None)) + self.assertSequenceEqual(new_sys_exc_info, new_exc_info) + else: + self.assertTrue(False) + @unittest.skipUnless(threading, 'Threading required for this test.') class TestPendingCalls(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14098: New functions PyErr_GetExcInfo and PyErr_SetExcInfo. + Patch by Stefan Behnel. + - Issue #14385: It is now possible to use a custom type for the __builtins__ namespace, instead of a dict. It can be used for sandboxing for example. Raise also a NameError instead of ImportError if __build_class__ name if not diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1639,6 +1639,29 @@ return NULL; } +static PyObject * +test_set_exc_info(PyObject *self, PyObject *args) +{ + PyObject *orig_exc; + PyObject *new_type, *new_value, *new_tb; + PyObject *type, *value, *tb; + if (!PyArg_ParseTuple(args, "OOO:test_set_exc_info", + &new_type, &new_value, &new_tb)) + return NULL; + + PyErr_GetExcInfo(&type, &value, &tb); + + Py_INCREF(new_type); + Py_INCREF(new_value); + Py_INCREF(new_tb); + PyErr_SetExcInfo(new_type, new_value, new_tb); + + orig_exc = PyTuple_Pack(3, type ? type : Py_None, value ? value : Py_None, tb ? tb : Py_None); + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tb); + return orig_exc; +} static int test_run_counter = 0; @@ -2471,6 +2494,7 @@ #endif {"traceback_print", traceback_print, METH_VARARGS}, {"exception_print", exception_print, METH_VARARGS}, + {"set_exc_info", test_set_exc_info, METH_VARARGS}, {"argparsing", argparsing, METH_VARARGS}, {"code_newempty", code_newempty, METH_VARARGS}, {"make_exception_with_doc", (PyCFunction)make_exception_with_doc, diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -320,6 +320,39 @@ PyErr_Restore(NULL, NULL, NULL); } +void +PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) +{ + PyThreadState *tstate = PyThreadState_GET(); + + *p_type = tstate->exc_type; + *p_value = tstate->exc_value; + *p_traceback = tstate->exc_traceback; + + Py_XINCREF(*p_type); + Py_XINCREF(*p_value); + Py_XINCREF(*p_traceback); +} + +void +PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback) +{ + PyObject *oldtype, *oldvalue, *oldtraceback; + PyThreadState *tstate = PyThreadState_GET(); + + oldtype = tstate->exc_type; + oldvalue = tstate->exc_value; + oldtraceback = tstate->exc_traceback; + + tstate->exc_type = p_type; + tstate->exc_value = p_value; + tstate->exc_traceback = p_traceback; + + Py_XDECREF(oldtype); + Py_XDECREF(oldvalue); + Py_XDECREF(oldtraceback); +} + /* Convenience functions to set a type error exception and return 0 */ int -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 19 18:23:57 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 19 Apr 2012 18:23:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_refleak=3A_PyObject=5FG?= =?utf8?q?etItem_returns_a_new_reference=2C_not_a_borrowed_one_like?= Message-ID: http://hg.python.org/cpython/rev/293180d199f2 changeset: 76419:293180d199f2 user: Antoine Pitrou date: Thu Apr 19 18:21:04 2012 +0200 summary: Fix refleak: PyObject_GetItem returns a new reference, not a borrowed one like PyDict_GetItem. files: Python/ceval.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1940,6 +1940,7 @@ "__build_class__ not found"); break; } + Py_INCREF(x); } else { PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__); @@ -1953,7 +1954,6 @@ break; } } - Py_INCREF(x); PUSH(x); break; } @@ -2092,6 +2092,7 @@ } if (x == NULL) { x = PyDict_GetItem(f->f_globals, w); + Py_XINCREF(x); if (x == NULL) { if (PyDict_CheckExact(f->f_builtins)) { x = PyDict_GetItem(f->f_builtins, w); @@ -2101,6 +2102,7 @@ NAME_ERROR_MSG, w); break; } + Py_INCREF(x); } else { x = PyObject_GetItem(f->f_builtins, w); @@ -2113,7 +2115,6 @@ } } } - Py_INCREF(x); } PUSH(x); DISPATCH(); @@ -2186,7 +2187,6 @@ break; } } - Py_INCREF(x); PUSH(x); DISPATCH(); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 19 19:42:30 2012 From: python-checkins at python.org (barry.warsaw) Date: Thu, 19 Apr 2012 19:42:30 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Guido_suggests_alternative_lan?= =?utf8?q?guage_for_whitespace_around_operators=2E?= Message-ID: http://hg.python.org/peps/rev/37af28ad2972 changeset: 4276:37af28ad2972 user: Barry Warsaw date: Thu Apr 19 13:42:24 2012 -0400 summary: Guido suggests alternative language for whitespace around operators. files: pep-0008.txt | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -305,7 +305,11 @@ ``>=``, ``in``, ``not in``, ``is``, ``is not``), Booleans (``and``, ``or``, ``not``). -- Use spaces around arithmetic operators: +- If operators with different priorities are used, consider adding + whitespace around the operators with the lowest priority(ies). Use + your own judgement; however, never use more than one space, and + always have the same amount of whitespace on both sides of a binary + operator. Yes:: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 22:17:50 2012 From: python-checkins at python.org (eric.smith) Date: Thu, 19 Apr 2012 22:17:50 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Added_PEP_420=2E_Thanks_to_MvL?= =?utf8?q?=2E_Much_of_the_text_comes_from_PEP_382_and_his_recap?= Message-ID: http://hg.python.org/peps/rev/6a8bb739ef28 changeset: 4277:6a8bb739ef28 parent: 4275:34076bfed420 user: Eric V. Smith date: Thu Apr 19 16:16:16 2012 -0400 summary: Added PEP 420. Thanks to MvL. Much of the text comes from PEP 382 and his recap of the PyCon discussion. files: pep-0420.txt | 193 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 193 insertions(+), 0 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt new file mode 100644 --- /dev/null +++ b/pep-0420.txt @@ -0,0 +1,193 @@ +PEP: 420 +Title: Implicit Namespace Packages +Version: $Revision$ +Last-Modified: $Date$ +Author: Eric V. Smith +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 19-Apr-2012 +Python-Version: 3.3 +Post-History: + +Abstract +======== + +Namespace packages are a mechanism for splitting a single Python +package across multiple directories on disk. In current Python +versions, an algorithm to compute the packages __path__ must be +formulated. With the enhancement proposed here, the import machinery +itself will construct the list of directories that make up the +package. This PEP builds upon the work started in rejected PEPs 382 +and 402. + +Terminology +=========== + +Within this PEP, the term package refers to Python packages as defined +by Python's import statement. The term distribution refers to +separately installable sets of Python modules as stored in the Python +package index, and installed by distutils or setuptools. The term +vendor package refers to groups of files installed by an operating +system's packaging mechanism (e.g. Debian or Redhat packages install +on Linux systems). + +The term portion refers to a set of files in a single directory (possibly +stored in a zip file) that contribute to a namespace package. + +The term "regular package" refers to packages as they are implemented +in Python 3.2. + +This PEP describes a new type of package, the "namespace package". + +Namespace packages today +======================== + +Python currently provides the pkgutil.extend_path to denote a package as +a namespace package. The recommended way of using it is to put:: + + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) + +in the package's ``__init__.py``. Every distribution needs to provide +the same contents in its ``__init__.py``, so that extend_path is +invoked independent of which portion of the package gets imported +first. As a consequence, the package's ``__init__.py`` cannot +practically define any names as it depends on the order of the package +fragments on sys.path which portion is imported first. As a special +feature, extend_path reads files named ``.pkg`` which +allow to declare additional portions. + +setuptools provides a similar function pkg_resources.declare_namespace +that is used in the form:: + + import pkg_resources + pkg_resources.declare_namespace(__name__) + +In the portion's __init__.py, no assignment to __path__ is necessary, +as declare_namespace modifies the package __path__ through sys.modules. +As a special feature, declare_namespace also supports zip files, and +registers the package name internally so that future additions to sys.path +by setuptools can properly add additional portions to each package. + +setuptools allows declaring namespace packages in a distribution's +setup.py, so that distribution developers don't need to put the +magic __path__ modification into __init__.py themselves. + +Rationale +========= + +The current imperative approach to namespace packages has lead to +multiple slightly-incompatible mechanisms for providing namespace +packages. For example, pkgutil supports ``*.pkg`` files; setuptools +doesn't. Likewise, setuptools supports inspecting zip files, and +supports adding portions to its _namespace_packages variable, whereas +pkgutil doesn't. + +Namespace packages need to be installed in one of two ways: either all +portions of a namespace will be combined into a single directory (and +therefore a single entry in sys.path), or each portion will be +installed in its own directory (and each portion will have a distinct +sys.path entry). + +The current imperative approach causes problems for system vendors. +Vendor packages typically must not provide overlapping files, and an +attempt to install a vendor package that has a file already on disk +will fail or cause unpredictable behavior. As vendors might chose to +package distributions such that they will end up all in a single +directory for the namespace package, all portions would contribute +conflicting __init__.py files. + +Specification +============= + +Regular packages will continue to have an __init__.py and will reside +in a single directory. + +Namespace packages cannot contain an __init__.py. As a consequence, +extend_path and declare_namespace become obsolete. There will be no +marker file or directory for specifing a namespace package. + +During import processing, the import machinery will continue to +iterate over the parent path as it does in Python 3.2. While looking +for a module or package named "foo": + + * If foo/__init__.py is found, a regular package is imported. + * If not, but foo.{py,pyc,so,pyd} is found, a module is imported. + * If not, but foo is found and is a directory, it is recorded. + +If the scan along the parent path completes without finding a module +or package, then a namespace package is created. The new namespace +package: + + * Has a __file__ set to the first directory that was found during the + scan, including the trailing path separator. + * Has a __path__ set to the list of directories there were found and + recorded during the scan. + +There is no mechanism to recompute the __path__ once a namespace +package has been created. + +Note that if "import foo" is executed and "foo" is found as a +namespace package (using the above rules), then "foo" is immediately +created as a package. The creation of the namespace package is not +deferred until a sub-level import occurs. + +Impact on Import Hooks +---------------------- + +To be determined in the sample implementation. + +Discussion +========== + +There is no intention to remove support of regular packages. If there +is no intention that a package is a namespace package, then there is a +performance advantage to it being a regular package. Creation and +loading of the package can take place once it is located along the +path. With namespace packages, all entries in the path must be +scanned. + +At PyCon 2012, we had a discussion about namespace packages at which +PEP 382 and PEP 402 were rejected, to be replaced by this PEP [1]_. + +Nick Coglan presented a list of his objections to this proposal +[2]_. They are: + + * Implicit package directories go against the Zen of Python + + * Implicit package directories pose awkward backwards compatibility + challenges + + * Implicit package directories introduce ambiguity into filesystem + layouts + + * Implicit package directories will permanently entrench current + newbie-hostile behaviour in __main__ + +(These need to be addressed here.) + + +References +========== + +.. [1] Namespace Packages resolution + (http://mail.python.org/pipermail/import-sig/2012-March/000421.html) + +.. [2] Nick Coglan's objection to the lack of marker files or directories + (http://mail.python.org/pipermail/import-sig/2012-March/000423.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: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 22:17:51 2012 From: python-checkins at python.org (eric.smith) Date: Thu, 19 Apr 2012 22:17:51 +0200 Subject: [Python-checkins] =?utf8?q?peps_=28merge_default_-=3E_default=29?= =?utf8?q?=3A_Merge_heads=2E?= Message-ID: http://hg.python.org/peps/rev/361d4ca5d360 changeset: 4278:361d4ca5d360 parent: 4277:6a8bb739ef28 parent: 4276:37af28ad2972 user: Eric V. Smith date: Thu Apr 19 16:17:45 2012 -0400 summary: Merge heads. files: pep-0008.txt | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -305,7 +305,11 @@ ``>=``, ``in``, ``not in``, ``is``, ``is not``), Booleans (``and``, ``or``, ``not``). -- Use spaces around arithmetic operators: +- If operators with different priorities are used, consider adding + whitespace around the operators with the lowest priority(ies). Use + your own judgement; however, never use more than one space, and + always have the same amount of whitespace on both sides of a binary + operator. Yes:: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 19 23:26:53 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 19 Apr 2012 23:26:53 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Patch_bench=5Ftime?= =?utf8?q?=2Ec_to_support_systems_without_clock=5Fgettime=28=29?= Message-ID: http://hg.python.org/peps/rev/0705221c05c3 changeset: 4279:0705221c05c3 user: Victor Stinner date: Thu Apr 19 23:26:51 2012 +0200 summary: PEP 418: Patch bench_time.c to support systems without clock_gettime() files: pep-0418/bench_time.c | 47 ++++++++++++++++++++++++------ 1 files changed, 37 insertions(+), 10 deletions(-) diff --git a/pep-0418/bench_time.c b/pep-0418/bench_time.c --- a/pep-0418/bench_time.c +++ b/pep-0418/bench_time.c @@ -8,12 +8,20 @@ #include #include +#ifdef CLOCK_REALTIME +# define HAVE_CLOCK_GETTIME +#else +typedef int clockid_t; +#endif + #define NRUN 5 -#define NLOOP 1000000 +#define NLOOP 100000 #define UNROLL(expr) \ expr; expr; expr; expr; expr; expr; expr; expr; expr; expr #define NUNROLL 10 +#ifdef HAVE_CLOCK_GETTIME + typedef struct { const char *name; clockid_t identifier; @@ -80,6 +88,8 @@ } } +#endif /* HAVE_CLOCK_GETTIME */ + void bench_time(clockid_t clkid) { unsigned long loop; @@ -117,25 +127,40 @@ { unsigned int run; double dt, best; - struct timespec before, after, tmpspec; +#ifdef HAVE_CLOCK_GETTIME + struct timespec before, after; +#else + struct timeval before, after; +#endif struct timeval tmpval; - best = 0; + best = -1.0; for (run=0; run= before.tv_nsec) - dt += (after.tv_nsec - before.tv_nsec) * 1e-9; + dt += (after.tv_nsec - before.tv_nsec); else - { - dt -= (before.tv_nsec - after.tv_nsec) * 1e-9; - } - dt *= (double)1e9 / NLOOP / NUNROLL; + dt -= (before.tv_nsec - after.tv_nsec); +#else + gettimeofday(&before, NULL); + (*func) (clkid); + gettimeofday(&after, NULL); - if (best != 0.0) { + dt = (after.tv_sec - before.tv_sec) * 1e9; + if (after.tv_usec >= before.tv_usec) + dt += (after.tv_usec - before.tv_usec) * 1e3; + else + dt -= (before.tv_usec - after.tv_usec) * 1e3; +#endif + dt /= NLOOP; + dt /= NUNROLL; + + if (best != -1.0) { if (dt < best) best = dt; } @@ -147,12 +172,14 @@ int main() { +#ifdef HAVE_CLOCK_GETTIME clockid_t clkid; int i; for (i=0; i http://hg.python.org/cpython/rev/ab9d6c4907e7 changeset: 76420:ab9d6c4907e7 branch: 2.7 parent: 76413:36c901fcfcda user: Antoine Pitrou date: Thu Apr 19 23:55:01 2012 +0200 summary: Issue #14308: Fix an exception when a "dummy" thread is in the threading module's active list after a fork(). files: Lib/test/test_threading.py | 29 ++++++++++++++++++++++++++ Lib/threading.py | 4 +++ Misc/NEWS | 3 ++ 3 files changed, 36 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -2,6 +2,8 @@ import test.test_support from test.test_support import verbose +from test.script_helper import assert_python_ok + import random import re import sys @@ -414,6 +416,33 @@ msg=('%d references still around' % sys.getrefcount(weak_raising_cyclic_object()))) + @unittest.skipUnless(hasattr(os, 'fork'), 'test needs fork()') + def test_dummy_thread_after_fork(self): + # Issue #14308: a dummy thread in the active list doesn't mess up + # the after-fork mechanism. + code = """if 1: + import thread, threading, os, time + + def background_thread(evt): + # Creates and registers the _DummyThread instance + threading.current_thread() + evt.set() + time.sleep(10) + + evt = threading.Event() + thread.start_new_thread(background_thread, (evt,)) + evt.wait() + assert threading.active_count() == 2, threading.active_count() + if os.fork() == 0: + assert threading.active_count() == 1, threading.active_count() + os._exit(0) + else: + os.wait() + """ + _, out, err = assert_python_ok("-c", code) + self.assertEqual(out, '') + self.assertEqual(err, '') + class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -605,6 +605,10 @@ pass def __stop(self): + # DummyThreads delete self.__block, but they have no waiters to + # notify anyway (join() is forbidden on them). + if not hasattr(self, '_Thread__block'): + return self.__block.acquire() self.__stopped = True self.__block.notify_all() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Library ------- +- Issue #14308: Fix an exception when a "dummy" thread is in the threading + module's active list after a fork(). + - Issue #14538: HTMLParser can now parse correctly start tags that contain a bare '/'. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 00:06:43 2012 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 20 Apr 2012 00:06:43 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0MzA4?= =?utf8?q?=3A_Fix_an_exception_when_a_=22dummy=22_thread_is_in_the_threadi?= =?utf8?q?ng?= Message-ID: http://hg.python.org/cpython/rev/41c64c700e1e changeset: 76421:41c64c700e1e branch: 3.2 parent: 76416:c4c67c2d8ffc user: Antoine Pitrou date: Thu Apr 19 23:55:01 2012 +0200 summary: Issue #14308: Fix an exception when a "dummy" thread is in the threading module's active list after a fork(). files: Lib/test/test_threading.py | 29 ++++++++++++++++++++++++++ Lib/threading.py | 3 ++ Misc/NEWS | 3 ++ 3 files changed, 35 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -2,6 +2,8 @@ import test.support from test.support import verbose, strip_python_stderr, import_module +from test.script_helper import assert_python_ok + import random import re import sys @@ -407,6 +409,33 @@ t.daemon = True self.assertTrue('daemon' in repr(t)) + @unittest.skipUnless(hasattr(os, 'fork'), 'test needs fork()') + def test_dummy_thread_after_fork(self): + # Issue #14308: a dummy thread in the active list doesn't mess up + # the after-fork mechanism. + code = """if 1: + import _thread, threading, os, time + + def background_thread(evt): + # Creates and registers the _DummyThread instance + threading.current_thread() + evt.set() + time.sleep(10) + + evt = threading.Event() + _thread.start_new_thread(background_thread, (evt,)) + evt.wait() + assert threading.active_count() == 2, threading.active_count() + if os.fork() == 0: + assert threading.active_count() == 1, threading.active_count() + os._exit(0) + else: + os.wait() + """ + _, out, err = assert_python_ok("-c", code) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -1007,6 +1007,9 @@ def _set_daemon(self): return True + def _stop(self): + pass + def join(self, timeout=None): assert False, "cannot join a dummy thread" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,9 @@ Library ------- +- Issue #14308: Fix an exception when a "dummy" thread is in the threading + module's active list after a fork(). + - Issue #14538: HTMLParser can now parse correctly start tags that contain a bare '/'. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 00:06:44 2012 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 20 Apr 2012 00:06:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314308=3A_Fix_an_exception_when_a_dummy_thread_is_in?= =?utf8?q?_the_threading_module=27s?= Message-ID: http://hg.python.org/cpython/rev/e3ea462cb181 changeset: 76422:e3ea462cb181 parent: 76419:293180d199f2 parent: 76421:41c64c700e1e user: Antoine Pitrou date: Fri Apr 20 00:05:17 2012 +0200 summary: Issue #14308: Fix an exception when a dummy thread is in the threading module's active list after a fork(). files: Lib/test/test_threading.py | 29 ++++++++++++++++++++++++++ Lib/threading.py | 3 ++ Misc/NEWS | 3 ++ 3 files changed, 35 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -2,6 +2,8 @@ import test.support from test.support import verbose, strip_python_stderr, import_module +from test.script_helper import assert_python_ok + import random import re import sys @@ -415,6 +417,33 @@ t = threading.Thread(daemon=True) self.assertTrue(t.daemon) + @unittest.skipUnless(hasattr(os, 'fork'), 'test needs fork()') + def test_dummy_thread_after_fork(self): + # Issue #14308: a dummy thread in the active list doesn't mess up + # the after-fork mechanism. + code = """if 1: + import _thread, threading, os, time + + def background_thread(evt): + # Creates and registers the _DummyThread instance + threading.current_thread() + evt.set() + time.sleep(10) + + evt = threading.Event() + _thread.start_new_thread(background_thread, (evt,)) + evt.wait() + assert threading.active_count() == 2, threading.active_count() + if os.fork() == 0: + assert threading.active_count() == 1, threading.active_count() + os._exit(0) + else: + os.wait() + """ + _, out, err = assert_python_ok("-c", code) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -871,6 +871,9 @@ with _active_limbo_lock: _active[self._ident] = self + def _stop(self): + pass + def join(self, timeout=None): assert False, "cannot join a dummy thread" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -55,6 +55,9 @@ Library ------- +- Issue #14308: Fix an exception when a "dummy" thread is in the threading + module's active list after a fork(). + - Issue #11750: The Windows API functions scattered in the _subprocess and _multiprocessing.win32 modules now live in a single module "_winapi". Patch by sbt. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 00:08:46 2012 From: python-checkins at python.org (larry.hastings) Date: Fri, 20 Apr 2012 00:08:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314127=3A_Add_st=5F?= =?utf8?q?=7Bcma=7Dtime=5Fns_fields_to_os=2Estat=28=29_result_object=2E?= Message-ID: http://hg.python.org/cpython/rev/f554043badec changeset: 76423:f554043badec user: Larry Hastings date: Thu Apr 19 15:07:49 2012 -0700 summary: Issue #14127: Add st_{cma}time_ns fields to os.stat() result object. files: Doc/library/os.rst | 32 ++++++++++-- Include/pytime.h | 4 + Lib/test/test_os.py | 7 ++ Modules/_testcapimodule.c | 11 ---- Modules/posixmodule.c | 66 ++++++++++++++++++++------ Python/pytime.c | 11 ++++ 6 files changed, 97 insertions(+), 34 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2011,8 +2011,8 @@ Perform the equivalent of a :c:func:`stat` system call on the given path. (This function follows symlinks; to stat a symlink use :func:`lstat`.) - The return value is an object whose attributes correspond to the members - of the :c:type:`stat` structure, namely: + The return value is an object whose attributes correspond roughly + to the members of the :c:type:`stat` structure, namely: * :attr:`st_mode` - protection bits, * :attr:`st_ino` - inode number, @@ -2021,10 +2021,18 @@ * :attr:`st_uid` - user id of owner, * :attr:`st_gid` - group id of owner, * :attr:`st_size` - size of file, in bytes, - * :attr:`st_atime` - time of most recent access, - * :attr:`st_mtime` - time of most recent content modification, - * :attr:`st_ctime` - platform dependent; time of most recent metadata change on - Unix, or the time of creation on Windows) + * :attr:`st_atime` - time of most recent access expressed in seconds, + * :attr:`st_mtime` - time of most recent content modification + expressed in seconds, + * :attr:`st_ctime` - platform dependent; time of most recent metadata + change on Unix, or the time of creation on Windows, expressed in seconds + * :attr:`st_atime_ns` - time of most recent access + expressed in nanoseconds as an integer, + * :attr:`st_mtime_ns` - time of most recent content modification + expressed in nanoseconds as an integer, + * :attr:`st_ctime_ns` - platform dependent; time of most recent metadata + change on Unix, or the time of creation on Windows, + expressed in nanoseconds as an integer On some Unix systems (such as Linux), the following attributes may also be available: @@ -2054,6 +2062,14 @@ or FAT32 file systems, :attr:`st_mtime` has 2-second resolution, and :attr:`st_atime` has only 1-day resolution. See your operating system documentation for details. + Similarly, although :attr:`st_atime_ns`, :attr:`st_mtime_ns`, + and :attr:`st_ctime_ns` are always expressed in nanoseconds, many + systems do not provide nanosecond precision. On systems that do + provide nanosecond precision, the floating-point object used to + store :attr:`st_atime`, :attr:`st_mtime`, and :attr:`st_ctime` + cannot preserve all of it, and as such will be slightly inexact. + If you need the exact timestamps you should always use + :attr:`st_atime_ns`, :attr:`st_mtime_ns`, and :attr:`st_ctime_ns`. For backward compatibility, the return value of :func:`~os.stat` is also accessible as a tuple of at least 10 integers giving the most important (and portable) @@ -2081,6 +2097,10 @@ Availability: Unix, Windows. + .. versionadded:: 3.3 + The :attr:`st_atime_ns`, :attr:`st_mtime_ns`, + and :attr:`st_ctime_ns` members. + .. function:: stat_float_times([newvalue]) diff --git a/Include/pytime.h b/Include/pytime.h --- a/Include/pytime.h +++ b/Include/pytime.h @@ -44,6 +44,10 @@ PyObject *obj, time_t *sec); +/* Convert a time_t to a PyLong. */ +PyAPI_FUNC(PyObject *) _PyLong_FromTime_t( + time_t sec); + /* Convert a number of seconds, int or float, to a timeval structure. usec is in the range [0; 999999] and rounded towards zero. For example, -1.2 is converted to (-2, 800000). */ diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -191,6 +191,13 @@ result[getattr(stat, name)]) self.assertIn(attr, members) + # Make sure that the st_?time and st_?time_ns fields roughly agree + # (they should always agree up to the tens-of-microseconds magnitude) + for name in 'st_atime st_mtime st_ctime'.split(): + floaty = int(getattr(result, name) * 100000) + nanosecondy = getattr(result, name + "_ns") // 10000 + self.assertEqual(floaty, nanosecondy) + try: result[200] self.fail("No exception thrown") diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2362,17 +2362,6 @@ return PyLong_FromLong(r); } -static PyObject* -_PyLong_FromTime_t(time_t value) -{ -#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG - return PyLong_FromLongLong(value); -#else - assert(sizeof(time_t) <= sizeof(long)); - return PyLong_FromLong(value); -#endif -} - static PyObject * test_pytime_object_to_time_t(PyObject *self, PyObject *args) { diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1550,6 +1550,9 @@ {"st_atime", "time of last access"}, {"st_mtime", "time of last modification"}, {"st_ctime", "time of last change"}, + {"st_atime_ns", "time of last access in nanoseconds"}, + {"st_mtime_ns", "time of last modification in nanoseconds"}, + {"st_ctime_ns", "time of last change in nanoseconds"}, #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE {"st_blksize", "blocksize for filesystem I/O"}, #endif @@ -1572,9 +1575,9 @@ }; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE -#define ST_BLKSIZE_IDX 13 +#define ST_BLKSIZE_IDX 16 #else -#define ST_BLKSIZE_IDX 12 +#define ST_BLKSIZE_IDX 15 #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS @@ -1726,25 +1729,50 @@ return Py_None; } +static PyObject *billion = NULL; + static void fill_time(PyObject *v, int index, time_t sec, unsigned long nsec) { - PyObject *fval,*ival; -#if SIZEOF_TIME_T > SIZEOF_LONG - ival = PyLong_FromLongLong((PY_LONG_LONG)sec); -#else - ival = PyLong_FromLong((long)sec); -#endif - if (!ival) - return; + PyObject *s = _PyLong_FromTime_t(sec); + PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); + PyObject *s_in_ns = NULL; + PyObject *ns_total = NULL; + PyObject *float_s = NULL; + + if (!(s && ns_fractional)) + goto exit; + + s_in_ns = PyNumber_Multiply(s, billion); + if (!s_in_ns) + goto exit; + + ns_total = PyNumber_Add(s_in_ns, ns_fractional); + if (!ns_total) + goto exit; + if (_stat_float_times) { - fval = PyFloat_FromDouble(sec + 1e-9*nsec); - } else { - fval = ival; - Py_INCREF(fval); - } - PyStructSequence_SET_ITEM(v, index, ival); - PyStructSequence_SET_ITEM(v, index+3, fval); + float_s = PyFloat_FromDouble(sec + 1e-9*nsec); + if (!float_s) + goto exit; + } + else { + float_s = s; + Py_INCREF(float_s); + } + + PyStructSequence_SET_ITEM(v, index, s); + PyStructSequence_SET_ITEM(v, index+3, float_s); + PyStructSequence_SET_ITEM(v, index+6, ns_total); + s = NULL; + float_s = NULL; + ns_total = NULL; +exit: + Py_XDECREF(s); + Py_XDECREF(ns_fractional); + Py_XDECREF(s_in_ns); + Py_XDECREF(ns_total); + Py_XDECREF(float_s); } /* pack a system stat C structure into the Python stat tuple @@ -11627,6 +11655,10 @@ PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType); + billion = PyLong_FromLong(1000000000); + if (!billion) + return NULL; + return m; } diff --git a/Python/pytime.c b/Python/pytime.c --- a/Python/pytime.c +++ b/Python/pytime.c @@ -96,6 +96,17 @@ return (time_t)val; } +PyObject * +_PyLong_FromTime_t(time_t t) +{ +#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG + return PyLong_FromLongLong((PY_LONG_LONG)t); +#else + assert(sizeof(time_t) <= sizeof(long)); + return PyLong_FromLong((long)t); +#endif +} + static int _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, double denominator) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 00:10:11 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 00:10:11 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Grammar_fixes_by_Brett_Cannon?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/peps/rev/283db7a1042a changeset: 4280:283db7a1042a user: Eric V. Smith date: Thu Apr 19 18:10:05 2012 -0400 summary: Grammar fixes by Brett Cannon. files: pep-0420.txt | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -24,15 +24,15 @@ Terminology =========== -Within this PEP, the term package refers to Python packages as defined -by Python's import statement. The term distribution refers to +Within this PEP, the term "package" refers to Python packages as defined +by Python's import statement. The term "distribution" refers to separately installable sets of Python modules as stored in the Python package index, and installed by distutils or setuptools. The term -vendor package refers to groups of files installed by an operating +"vendor package" refers to groups of files installed by an operating system's packaging mechanism (e.g. Debian or Redhat packages install on Linux systems). -The term portion refers to a set of files in a single directory (possibly +The term "portion" refers to a set of files in a single directory (possibly stored in a zip file) that contribute to a namespace package. The term "regular package" refers to packages as they are implemented @@ -58,8 +58,8 @@ feature, extend_path reads files named ``.pkg`` which allow to declare additional portions. -setuptools provides a similar function pkg_resources.declare_namespace -that is used in the form:: +setuptools provides a similar function named +pkg_resources.declare_namespace that is used in the form:: import pkg_resources pkg_resources.declare_namespace(__name__) @@ -93,7 +93,7 @@ The current imperative approach causes problems for system vendors. Vendor packages typically must not provide overlapping files, and an attempt to install a vendor package that has a file already on disk -will fail or cause unpredictable behavior. As vendors might chose to +will fail or cause unpredictable behavior. As vendors might choose to package distributions such that they will end up all in a single directory for the namespace package, all portions would contribute conflicting __init__.py files. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 00:56:26 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 00:56:26 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Note_that_ImportError_will_no_?= =?utf8?q?longer_be_raised_due_to_a_missing_=5F=5Finit=5F=5F=2Epy?= Message-ID: http://hg.python.org/peps/rev/af61fe9a56fb changeset: 4281:af61fe9a56fb user: Eric V. Smith date: Thu Apr 19 18:56:22 2012 -0400 summary: Note that ImportError will no longer be raised due to a missing __init__.py file. files: pep-0420.txt | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -148,6 +148,11 @@ path. With namespace packages, all entries in the path must be scanned. +Note that an ImportError will no longer be raised for a directory +lacking an ``__init__.py`` file. Such a directory will now be imported +as a namespace package, whereas in prior Python versions an +ImportError would be raised. + At PyCon 2012, we had a discussion about namespace packages at which PEP 382 and PEP 402 were rejected, to be replaced by this PEP [1]_. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 01:42:54 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 20 Apr 2012 01:42:54 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Close_=2314386=3A_Register_?= =?utf8?q?types=2EMappingProxyType_as_a_Mapping?= Message-ID: http://hg.python.org/cpython/rev/34af3e74292d changeset: 76424:34af3e74292d user: Victor Stinner date: Fri Apr 20 01:41:36 2012 +0200 summary: Close #14386: Register types.MappingProxyType as a Mapping files: Lib/collections/abc.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/collections/abc.py b/Lib/collections/abc.py --- a/Lib/collections/abc.py +++ b/Lib/collections/abc.py @@ -43,7 +43,7 @@ dict_values = type({}.values()) dict_items = type({}.items()) ## misc ## -dict_proxy = type(type.__dict__) +mappingproxy = type(type.__dict__) ### ONE-TRICK PONIES ### @@ -405,6 +405,8 @@ def __ne__(self, other): return not (self == other) +Mapping.register(mappingproxy) + class MappingView(Sized): -- Repository URL: http://hg.python.org/cpython From brett at python.org Fri Apr 20 04:59:18 2012 From: brett at python.org (Brett Cannon) Date: Thu, 19 Apr 2012 22:59:18 -0400 Subject: [Python-checkins] peps: Note that ImportError will no longer be raised due to a missing __init__.py In-Reply-To: References: Message-ID: It's actually an ImportWarning, not Error (or at least that's what I meant on import-sig). If the module is eventually found then there is no error. On Thu, Apr 19, 2012 at 18:56, eric.smith wrote: > http://hg.python.org/peps/rev/af61fe9a56fb > changeset: 4281:af61fe9a56fb > user: Eric V. Smith > date: Thu Apr 19 18:56:22 2012 -0400 > summary: > Note that ImportError will no longer be raised due to a missing > __init__.py file. > > files: > pep-0420.txt | 5 +++++ > 1 files changed, 5 insertions(+), 0 deletions(-) > > > diff --git a/pep-0420.txt b/pep-0420.txt > --- a/pep-0420.txt > +++ b/pep-0420.txt > @@ -148,6 +148,11 @@ > path. With namespace packages, all entries in the path must be > scanned. > > +Note that an ImportError will no longer be raised for a directory > +lacking an ``__init__.py`` file. Such a directory will now be imported > +as a namespace package, whereas in prior Python versions an > +ImportError would be raised. > + > At PyCon 2012, we had a discussion about namespace packages at which > PEP 382 and PEP 402 were rejected, to be replaced by this PEP [1]_. > > > -- > Repository URL: http://hg.python.org/peps > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From solipsis at pitrou.net Fri Apr 20 05:35:47 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 20 Apr 2012 05:35:47 +0200 Subject: [Python-checkins] Daily reference leaks (34af3e74292d): sum=0 Message-ID: results for 34af3e74292d on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogCGbNf_', '-x'] From python-checkins at python.org Fri Apr 20 10:51:44 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 10:51:44 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_ImportError_-=3E_ImportWarning?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/peps/rev/594351f1c313 changeset: 4282:594351f1c313 user: Eric V. Smith date: Fri Apr 20 04:51:07 2012 -0400 summary: ImportError -> ImportWarning. files: pep-0420.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -148,7 +148,7 @@ path. With namespace packages, all entries in the path must be scanned. -Note that an ImportError will no longer be raised for a directory +Note that an ImportWarning will no longer be raised for a directory lacking an ``__init__.py`` file. Such a directory will now be imported as a namespace package, whereas in prior Python versions an ImportError would be raised. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 12:15:17 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 12:15:17 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Improved_paragraph_on_=5F=5Fpa?= =?utf8?q?th=5F=5F_recalculation=2E_Suggested_by_Nick_Coglan=2E?= Message-ID: http://hg.python.org/peps/rev/305efdde744a changeset: 4283:305efdde744a user: Eric V. Smith date: Fri Apr 20 06:15:03 2012 -0400 summary: Improved paragraph on __path__ recalculation. Suggested by Nick Coglan. files: pep-0420.txt | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -125,8 +125,11 @@ * Has a __path__ set to the list of directories there were found and recorded during the scan. -There is no mechanism to recompute the __path__ once a namespace -package has been created. +There is no mechanism to automatically recompute the ``__path__`` if +``sys.path`` is altered after a namespace package has already been +created. However, existing namespace utilities (like +``pkgutil.extend_path()``) can be used to update them explicitly if +desired. Note that if "import foo" is executed and "foo" is found as a namespace package (using the above rules), then "foo" is immediately -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 12:20:30 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 12:20:30 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Another_improvement_by_Nick=3A?= =?utf8?q?_a_better_description_of_splitting_portions_among?= Message-ID: http://hg.python.org/peps/rev/139de1b8f702 changeset: 4284:139de1b8f702 user: Eric V. Smith date: Fri Apr 20 06:20:24 2012 -0400 summary: Another improvement by Nick: a better description of splitting portions among multiple directories. files: pep-0420.txt | 27 ++++++++++++++------------- 1 files changed, 14 insertions(+), 13 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -84,19 +84,20 @@ supports adding portions to its _namespace_packages variable, whereas pkgutil doesn't. -Namespace packages need to be installed in one of two ways: either all -portions of a namespace will be combined into a single directory (and -therefore a single entry in sys.path), or each portion will be -installed in its own directory (and each portion will have a distinct -sys.path entry). - -The current imperative approach causes problems for system vendors. -Vendor packages typically must not provide overlapping files, and an -attempt to install a vendor package that has a file already on disk -will fail or cause unpredictable behavior. As vendors might choose to -package distributions such that they will end up all in a single -directory for the namespace package, all portions would contribute -conflicting __init__.py files. +Namespace packages are designed to support being split across multiple +directories (and hence found via multiple sys.path entries). In this +configuration, it doesn't matter if multiple portions all provide an +``__init__.py`` file, so long as each portion correctly initializes +the namespace package. However, Linux distribution vendors (amongst +others) prefer to combine the separate portions and install them all +into the *same* filesystem directory. This creates a potential for +conflict, as the portions are now attempting to provide the *same* +file on the target system - something that is not allowed by many +package managers. Allowing implicit namespace packages means that the +requirement to provide an ``__init__.py`` file can be dropped +completely, and affected portions can be installed into a common +directory or split across multiple directories as distributions see +fit. Specification ============= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 12:30:00 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 12:30:00 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Cleanup=2E_Add_double_backtick?= =?utf8?q?s_where_needed=2E?= Message-ID: http://hg.python.org/peps/rev/f29b5cffab76 changeset: 4285:f29b5cffab76 user: Eric V. Smith date: Fri Apr 20 06:29:55 2012 -0400 summary: Cleanup. Add double backticks where needed. files: pep-0420.txt | 73 ++++++++++++++++++++------------------- 1 files changed, 38 insertions(+), 35 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -15,7 +15,7 @@ Namespace packages are a mechanism for splitting a single Python package across multiple directories on disk. In current Python -versions, an algorithm to compute the packages __path__ must be +versions, an algorithm to compute the packages ``__path__`` must be formulated. With the enhancement proposed here, the import machinery itself will construct the list of directories that make up the package. This PEP builds upon the work started in rejected PEPs 382 @@ -24,19 +24,20 @@ Terminology =========== -Within this PEP, the term "package" refers to Python packages as defined -by Python's import statement. The term "distribution" refers to -separately installable sets of Python modules as stored in the Python -package index, and installed by distutils or setuptools. The term -"vendor package" refers to groups of files installed by an operating -system's packaging mechanism (e.g. Debian or Redhat packages install -on Linux systems). +Within this PEP: -The term "portion" refers to a set of files in a single directory (possibly -stored in a zip file) that contribute to a namespace package. - -The term "regular package" refers to packages as they are implemented -in Python 3.2. + * "package" refers to Python packages as defined by Python's import + statement. + * "distribution" refers to separately installable sets of Python + modules as stored in the Python package index, and installed by + distutils or setuptools. + * "vendor package" refers to groups of files installed by an + operating system's packaging mechanism (e.g. Debian or Redhat + packages install on Linux systems). + * "portion" refers to a set of files in a single directory (possibly + stored in a zip file) that contribute to a namespace package. + * "regular package" refers to packages as they are implemented in + Python 3.2. This PEP describes a new type of package, the "namespace package". @@ -59,20 +60,21 @@ allow to declare additional portions. setuptools provides a similar function named -pkg_resources.declare_namespace that is used in the form:: +``pkg_resources.declare_namespace`` that is used in the form:: import pkg_resources pkg_resources.declare_namespace(__name__) -In the portion's __init__.py, no assignment to __path__ is necessary, -as declare_namespace modifies the package __path__ through sys.modules. -As a special feature, declare_namespace also supports zip files, and -registers the package name internally so that future additions to sys.path -by setuptools can properly add additional portions to each package. +In the portion's ``__init__.py``, no assignment to ``__path__`` is +necessary, as ``declare_namespace`` modifies the package ``__path__`` +through ``sys.modules``. As a special feature, ``declare_namespace`` +also supports zip files, and registers the package name internally so +that future additions to ``sys.path`` by setuptools can properly add +additional portions to each package. setuptools allows declaring namespace packages in a distribution's -setup.py, so that distribution developers don't need to put the -magic __path__ modification into __init__.py themselves. +``setup.py``, so that distribution developers don't need to put the +magic ``__path__`` modification into ``__init__.py`` themselves. Rationale ========= @@ -81,8 +83,8 @@ multiple slightly-incompatible mechanisms for providing namespace packages. For example, pkgutil supports ``*.pkg`` files; setuptools doesn't. Likewise, setuptools supports inspecting zip files, and -supports adding portions to its _namespace_packages variable, whereas -pkgutil doesn't. +supports adding portions to its ``_namespace_packages`` variable, +whereas pkgutil doesn't. Namespace packages are designed to support being split across multiple directories (and hence found via multiple sys.path entries). In this @@ -102,29 +104,30 @@ Specification ============= -Regular packages will continue to have an __init__.py and will reside -in a single directory. +Regular packages will continue to have an ``__init__.py`` and will +reside in a single directory. -Namespace packages cannot contain an __init__.py. As a consequence, -extend_path and declare_namespace become obsolete. There will be no -marker file or directory for specifing a namespace package. +Namespace packages cannot contain an ``__init__.py``. As a +consequence, ``extend_path`` and ``declare_namespace`` become +obsolete. There will be no marker file or directory for specifing a +namespace package. During import processing, the import machinery will continue to iterate over the parent path as it does in Python 3.2. While looking for a module or package named "foo": - * If foo/__init__.py is found, a regular package is imported. - * If not, but foo.{py,pyc,so,pyd} is found, a module is imported. - * If not, but foo is found and is a directory, it is recorded. + * If ``foo/__init__.py`` is found, a regular package is imported. + * If not, but ``foo.{py,pyc,so,pyd}`` is found, a module is imported. + * If not, but ``foo`` is found and is a directory, it is recorded. If the scan along the parent path completes without finding a module or package, then a namespace package is created. The new namespace package: - * Has a __file__ set to the first directory that was found during the - scan, including the trailing path separator. - * Has a __path__ set to the list of directories there were found and - recorded during the scan. + * Has a ``__file__`` attribute set to the first directory that was + found during the scan, including the trailing path separator. + * Has a ``__path__`` attribute set to the list of directories there + were found and recorded during the scan. There is no mechanism to automatically recompute the ``__path__`` if ``sys.path`` is altered after a namespace package has already been -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 14:12:03 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 14:12:03 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_It=27s_finders_and_loaders_tha?= =?utf8?q?t_will_be_impacted=2E?= Message-ID: http://hg.python.org/peps/rev/e6377df308cb changeset: 4286:e6377df308cb user: Eric V. Smith date: Fri Apr 20 08:11:56 2012 -0400 summary: It's finders and loaders that will be impacted. files: pep-0420.txt | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -140,8 +140,8 @@ created as a package. The creation of the namespace package is not deferred until a sub-level import occurs. -Impact on Import Hooks ----------------------- +Impact on Import Finders and Loaders +------------------------------------ To be determined in the sample implementation. @@ -183,7 +183,7 @@ References ========== -.. [1] Namespace Packages resolution +.. [1] PyCon 2012 Namespace Package discussion outcome (http://mail.python.org/pipermail/import-sig/2012-March/000421.html) .. [2] Nick Coglan's objection to the lack of marker files or directories -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 14:18:13 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 14:18:13 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Fix_references_to_extend=5Fpat?= =?utf8?q?h_and_declare=5Fnamespace=2E_Also_make_it_clearer_that?= Message-ID: http://hg.python.org/peps/rev/a75039cb8152 changeset: 4287:a75039cb8152 user: Eric V. Smith date: Fri Apr 20 08:18:01 2012 -0400 summary: Fix references to extend_path and declare_namespace. Also make it clearer that these functions don't need to be removed: they just won't be needed for implicit namespace packages. files: pep-0420.txt | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -44,19 +44,19 @@ Namespace packages today ======================== -Python currently provides the pkgutil.extend_path to denote a package as +Python currently provides ``pkgutil.extend_path`` to denote a package as a namespace package. The recommended way of using it is to put:: from pkgutil import extend_path __path__ = extend_path(__path__, __name__) in the package's ``__init__.py``. Every distribution needs to provide -the same contents in its ``__init__.py``, so that extend_path is +the same contents in its ``__init__.py``, so that ``extend_path`` is invoked independent of which portion of the package gets imported first. As a consequence, the package's ``__init__.py`` cannot practically define any names as it depends on the order of the package fragments on sys.path which portion is imported first. As a special -feature, extend_path reads files named ``.pkg`` which +feature, ``extend_path`` reads files named ``.pkg`` which allow to declare additional portions. setuptools provides a similar function named @@ -108,9 +108,10 @@ reside in a single directory. Namespace packages cannot contain an ``__init__.py``. As a -consequence, ``extend_path`` and ``declare_namespace`` become -obsolete. There will be no marker file or directory for specifing a -namespace package. +consequence, ``pkgutil.extend_path`` and +``pkg_resources.declare_namespace`` become obsolete for purposes of +namespace package creation. There will be no marker file or directory +for specifing a namespace package. During import processing, the import machinery will continue to iterate over the parent path as it does in Python 3.2. While looking @@ -132,7 +133,7 @@ There is no mechanism to automatically recompute the ``__path__`` if ``sys.path`` is altered after a namespace package has already been created. However, existing namespace utilities (like -``pkgutil.extend_path()``) can be used to update them explicitly if +``pkgutil.extend_path``) can be used to update them explicitly if desired. Note that if "import foo" is executed and "foo" is found as a -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 14:36:01 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 14:36:01 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_More_backticks=2E?= Message-ID: http://hg.python.org/peps/rev/2e29a596f460 changeset: 4288:2e29a596f460 user: Eric V. Smith date: Fri Apr 20 08:35:55 2012 -0400 summary: More backticks. files: pep-0420.txt | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -55,9 +55,9 @@ invoked independent of which portion of the package gets imported first. As a consequence, the package's ``__init__.py`` cannot practically define any names as it depends on the order of the package -fragments on sys.path which portion is imported first. As a special -feature, ``extend_path`` reads files named ``.pkg`` which -allow to declare additional portions. +fragments on ``sys.path`` which portion is imported first. As a +special feature, ``extend_path`` reads files named +``.pkg`` which allow to declare additional portions. setuptools provides a similar function named ``pkg_resources.declare_namespace`` that is used in the form:: @@ -87,9 +87,9 @@ whereas pkgutil doesn't. Namespace packages are designed to support being split across multiple -directories (and hence found via multiple sys.path entries). In this -configuration, it doesn't matter if multiple portions all provide an -``__init__.py`` file, so long as each portion correctly initializes +directories (and hence found via multiple ``sys.path`` entries). In +this configuration, it doesn't matter if multiple portions all provide +an ``__init__.py`` file, so long as each portion correctly initializes the namespace package. However, Linux distribution vendors (amongst others) prefer to combine the separate portions and install them all into the *same* filesystem directory. This creates a potential for -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 14:37:25 2012 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 20 Apr 2012 14:37:25 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NjI5?= =?utf8?q?=3A_Raise_SyntaxError_in_tokenizer=2Edetect=5Fencoding?= Message-ID: http://hg.python.org/cpython/rev/b07488490001 changeset: 76425:b07488490001 branch: 3.2 parent: 76421:41c64c700e1e user: Martin v. L?wis date: Fri Apr 20 14:36:47 2012 +0200 summary: Issue #14629: Raise SyntaxError in tokenizer.detect_encoding if the first two lines have non-UTF-8 characters without an encoding declaration. files: Lib/test/test_tokenize.py | 10 ++++++++++ Lib/tokenize.py | 7 +++++-- Misc/NEWS | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -825,6 +825,16 @@ found, consumed_lines = detect_encoding(rl) self.assertEqual(found, "iso-8859-1") + def test_syntaxerror_latin1(self): + # Issue 14629: need to raise SyntaxError if the first + # line(s) have non-UTF-8 characters + lines = ( + b'print("\xdf")', # Latin-1: LATIN SMALL LETTER SHARP S + ) + readline = self.get_readline(lines) + self.assertRaises(SyntaxError, detect_encoding, readline) + + def test_utf8_normalization(self): # See get_normal_name() in tokenizer.c. encodings = ("utf-8", "utf-8-mac", "utf-8-unix") diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -292,9 +292,12 @@ def find_cookie(line): try: - line_string = line.decode('ascii') + # Decode as UTF-8. Either the line is an encoding declaration, + # in which case it should be pure ASCII, or it must be UTF-8 + # per default encoding. + line_string = line.decode('utf-8') except UnicodeDecodeError: - return None + raise SyntaxError("invalid or missing encoding declaration") matches = cookie_re.findall(line_string) if not matches: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,9 @@ Library ------- +- Issue #14629: Raise SyntaxError in tokenizer.detect_encoding if the + first two lines have non-UTF-8 characters without an encoding declaration. + - Issue #14308: Fix an exception when a "dummy" thread is in the threading module's active list after a fork(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 14:37:27 2012 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 20 Apr 2012 14:37:27 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2=3A_issue_14629?= Message-ID: http://hg.python.org/cpython/rev/98a6a57c5876 changeset: 76426:98a6a57c5876 parent: 76424:34af3e74292d parent: 76425:b07488490001 user: Martin v. L?wis date: Fri Apr 20 14:37:17 2012 +0200 summary: merge 3.2: issue 14629 files: Lib/test/test_tokenize.py | 10 ++++++++++ Lib/tokenize.py | 7 +++++-- Misc/NEWS | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -838,6 +838,16 @@ found, consumed_lines = detect_encoding(rl) self.assertEqual(found, "iso-8859-1") + def test_syntaxerror_latin1(self): + # Issue 14629: need to raise SyntaxError if the first + # line(s) have non-UTF-8 characters + lines = ( + b'print("\xdf")', # Latin-1: LATIN SMALL LETTER SHARP S + ) + readline = self.get_readline(lines) + self.assertRaises(SyntaxError, detect_encoding, readline) + + def test_utf8_normalization(self): # See get_normal_name() in tokenizer.c. encodings = ("utf-8", "utf-8-mac", "utf-8-unix") diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -364,9 +364,12 @@ def find_cookie(line): try: - line_string = line.decode('ascii') + # Decode as UTF-8. Either the line is an encoding declaration, + # in which case it should be pure ASCII, or it must be UTF-8 + # per default encoding. + line_string = line.decode('utf-8') except UnicodeDecodeError: - return None + raise SyntaxError("invalid or missing encoding declaration") matches = cookie_re.findall(line_string) if not matches: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -55,6 +55,9 @@ Library ------- +- Issue #14629: Raise SyntaxError in tokenizer.detect_encoding if the + first two lines have non-UTF-8 characters without an encoding declaration. + - Issue #14308: Fix an exception when a "dummy" thread is in the threading module's active list after a fork(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 15:22:32 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 20 Apr 2012 15:22:32 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Grammar_improvement=2E?= Message-ID: http://hg.python.org/peps/rev/6d1ff6c0bc8e changeset: 4289:6d1ff6c0bc8e user: Eric V. Smith date: Fri Apr 20 09:22:25 2012 -0400 summary: Grammar improvement. files: pep-0420.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -55,9 +55,9 @@ invoked independent of which portion of the package gets imported first. As a consequence, the package's ``__init__.py`` cannot practically define any names as it depends on the order of the package -fragments on ``sys.path`` which portion is imported first. As a -special feature, ``extend_path`` reads files named -``.pkg`` which allow to declare additional portions. +fragments on ``sys.path`` to determine which portion is imported +first. As a special feature, ``extend_path`` reads files named +``.pkg`` which allows declaration of additional portions. setuptools provides a similar function named ``pkg_resources.declare_namespace`` that is used in the form:: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 20 18:53:20 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 18:53:20 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Have_importlib=2Etest=2Ereg?= =?utf8?q?rtest_clear_sys=2Epath=5Fimporter=5Fcache_to_make?= Message-ID: http://hg.python.org/cpython/rev/068b5b48f649 changeset: 76427:068b5b48f649 user: Brett Cannon date: Fri Apr 20 12:51:44 2012 -0400 summary: Have importlib.test.regrtest clear sys.path_importer_cache to make sure finders from importlib are used instead of _frozen_importlib. files: Lib/importlib/test/regrtest.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/importlib/test/regrtest.py b/Lib/importlib/test/regrtest.py --- a/Lib/importlib/test/regrtest.py +++ b/Lib/importlib/test/regrtest.py @@ -12,5 +12,6 @@ if __name__ == '__main__': __builtins__.__import__ = importlib.__import__ + sys.path_importer_cache.clear() regrtest.main(quiet=True, verbose2=True) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 18:53:21 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 18:53:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314581=3A_Windows_u?= =?utf8?q?sers_are_allowed_to_import_modules_w/o_taking?= Message-ID: http://hg.python.org/cpython/rev/a32be109bd86 changeset: 76428:a32be109bd86 user: Brett Cannon date: Fri Apr 20 12:53:14 2012 -0400 summary: Issue #14581: Windows users are allowed to import modules w/o taking the file suffix's case into account, even when doing a case-sensitive import. files: Lib/importlib/_bootstrap.py | 18 +++++++++++++++++- Python/importlib.h | Bin 2 files changed, 17 insertions(+), 1 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -841,7 +841,23 @@ contents = _os.listdir(path) # We store two cached versions, to handle runtime changes of the # PYTHONCASEOK environment variable. - self._path_cache = set(contents) + if not sys.platform.startswith('win'): + self._path_cache = set(contents) + else: + # Windows users can import modules with case-insensitive file + # suffixes (for legacy reasons). Make the suffix lowercase here + # so it's done once instead of for every import. This is safe as + # the specified suffixes to check against are always specified in a + # case-sensitive manner. + lower_suffix_contents = set() + for item in contents: + name, dot, suffix = item.partition('.') + if dot: + new_name = '{}.{}'.format(name, suffix.lower()) + else: + new_name = name + lower_suffix_contents.add(new_name) + self._path_cache = lower_suffix_contents if sys.platform.startswith(CASE_INSENSITIVE_PLATFORMS): self._relaxed_path_cache = set(fn.lower() for fn in contents) diff --git a/Python/importlib.h b/Python/importlib.h index 3ccea93e3eec8e84972c009a5e59939e9a0d6aac..88b89edb779b33dda3c6b8f3af878d66bde2fd99 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 19:00:09 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 19:00:09 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314633=3A_Simplify_?= =?utf8?q?imp=2Efind=5Fmodue=28=29_test_after_fixes_from_issue?= Message-ID: http://hg.python.org/cpython/rev/a281a6622714 changeset: 76429:a281a6622714 user: Brett Cannon date: Fri Apr 20 12:59:59 2012 -0400 summary: Issue #14633: Simplify imp.find_modue() test after fixes from issue #14629 changed the message. files: Lib/test/test_imp.py | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -59,10 +59,8 @@ self.assertEqual(fd.encoding, encoding) path = [os.path.dirname(__file__)] - self.assertRaisesRegex(SyntaxError, - r"Non-UTF-8 code starting with '\\xf6'" - r" in file .*badsyntax_pep3120.py", - imp.find_module, 'badsyntax_pep3120', path) + with self.assertRaises(SyntaxError): + imp.find_module('badsyntax_pep3120', path) def test_issue1267(self): for mod, encoding, _ in self.test_strings: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 19:24:33 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 19:24:33 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314629=3A_Mention_t?= =?utf8?q?he_filename_in_SyntaxError_exceptions_from?= Message-ID: http://hg.python.org/cpython/rev/1b57de8a8383 changeset: 76430:1b57de8a8383 user: Brett Cannon date: Fri Apr 20 13:23:54 2012 -0400 summary: Issue #14629: Mention the filename in SyntaxError exceptions from tokenizer.detect_encoding() (when available). files: Lib/test/test_tokenize.py | 29 +++++++++++++++++++++++++++ Lib/tokenize.py | 22 +++++++++++++++++-- Misc/NEWS | 3 ++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -904,6 +904,35 @@ self.assertEqual(fp.encoding, 'utf-8-sig') self.assertEqual(fp.mode, 'r') + def test_filename_in_exception(self): + # When possible, include the file name in the exception. + path = 'some_file_path' + lines = ( + b'print("\xdf")', # Latin-1: LATIN SMALL LETTER SHARP S + ) + class Bunk: + def __init__(self, lines, path): + self.name = path + self._lines = lines + self._index = 0 + + def readline(self): + if self._index == len(lines): + raise StopIteration + line = lines[self._index] + self._index += 1 + return line + + with self.assertRaises(SyntaxError): + ins = Bunk(lines, path) + # Make sure lacking a name isn't an issue. + del ins.name + detect_encoding(ins.readline) + with self.assertRaisesRegex(SyntaxError, '.*{}'.format(path)): + ins = Bunk(lines, path) + detect_encoding(ins.readline) + + class TestTokenize(TestCase): def test_tokenize(self): diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -353,6 +353,10 @@ If no encoding is specified, then the default of 'utf-8' will be returned. """ + try: + filename = readline.__self__.name + except AttributeError: + filename = None bom_found = False encoding = None default = 'utf-8' @@ -369,7 +373,10 @@ # per default encoding. line_string = line.decode('utf-8') except UnicodeDecodeError: - raise SyntaxError("invalid or missing encoding declaration") + msg = "invalid or missing encoding declaration" + if filename is not None: + msg = '{} for {!r}'.format(msg, filename) + raise SyntaxError(msg) matches = cookie_re.findall(line_string) if not matches: @@ -379,12 +386,21 @@ codec = lookup(encoding) except LookupError: # This behaviour mimics the Python interpreter - raise SyntaxError("unknown encoding: " + encoding) + if filename is None: + msg = "unknown encoding: " + encoding + else: + msg = "unknown encoding for {!r}: {}".format(filename, + encoding) + raise SyntaxError(msg) if bom_found: if codec.name != 'utf-8': # This behaviour mimics the Python interpreter - raise SyntaxError('encoding problem: utf-8') + if filename is None: + msg = 'encoding problem: utf-8' + else: + msg = 'encoding problem for {!r}: utf-8'.format(filename) + raise SyntaxError(msg) encoding += '-sig' return encoding diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -55,6 +55,9 @@ Library ------- +- Issue #14629: tokenizer.detect_encoding will specify the filename in the + SyntaxError exception if found at readline.__self__.name. + - Issue #14629: Raise SyntaxError in tokenizer.detect_encoding if the first two lines have non-UTF-8 characters without an encoding declaration. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 19:34:39 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 19:34:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Try_to_debug_a_Windows_fail?= =?utf8?q?ure_on_the_buildbots=2E?= Message-ID: http://hg.python.org/cpython/rev/b0b0c8b175b6 changeset: 76431:b0b0c8b175b6 user: Brett Cannon date: Fri Apr 20 13:34:35 2012 -0400 summary: Try to debug a Windows failure on the buildbots. files: Lib/test/test_import.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -337,7 +337,7 @@ del sys.path[0] remove_files(TESTFN) - @unittest.skipUnless(sys.platform == "win32", "Windows specific") + @unittest.skipUnless(sys.platform == "win32", "Windows-specific") def test_extension_import_fail(self): # Issue 1559549 added `name` and `path` attributes to ImportError # in order to provide better detail. Issue 10854 implemented those @@ -352,6 +352,9 @@ import extension self.assertEqual(err.exception.name, pkg_name) # The path we get back has the dot-slash, e.g., ".\\extension.pyd" + self.assertIsNotNone(err.exception.path, + 'unexpected None for ImportError.path: ' + '{!r}'.format(err.exception)) self.assertEqual(os.path.relpath(err.exception.path), pkg_file) finally: unlink(pkg_file) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 20:00:11 2012 From: python-checkins at python.org (stefan.krah) Date: Fri, 20 Apr 2012 20:00:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_The_divmod_function_for_lar?= =?utf8?q?ge_numbers_now_has_an_ACL2_proof=2E_Related_changes=3A?= Message-ID: http://hg.python.org/cpython/rev/8f0307550f5a changeset: 76432:8f0307550f5a user: Stefan Krah date: Fri Apr 20 19:59:20 2012 +0200 summary: The divmod function for large numbers now has an ACL2 proof. Related changes: 1) Rename _mpd_qbarrett_divmod into _mpd_base_ndivmod: The function is only marginally related to either Barrett's algorithm or to the version in Hasselstrom's paper. 2) In places where the proof assumes exact operations, use new versions of add/sub/multiply that set NaN/Invalid_operation if this condition is not met. According to the proof this cannot happen, so this should be regarded as an extra safety net. 3) Raise Division_impossible for operands with a number of digits greater than MPD_MAX_PREC. This facilitates the audit of the function and can practically only occur in the 32-bit version under conditions where a MemoryError is already imminent. 4) Use _mpd_qmul() in places where the result can exceed MPD_MAX_PREC in a well defined manner. 5) Test for mpd_isspecial(qq) in a place where the addition of one can theoretically trigger a Malloc_error. 6) Remove redundant code in _mpd_qdivmod(). 7) Add many comments. files: Modules/_decimal/libmpdec/mpdecimal.c | 193 ++++++++++--- 1 files changed, 144 insertions(+), 49 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -105,8 +105,8 @@ const mpd_context_t *ctx, uint32_t *status); static inline void _mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status); -static void _mpd_qbarrett_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, - const mpd_t *b, uint32_t *status); +static void _mpd_base_ndivmod(mpd_t *q, mpd_t *r, const mpd_t *a, + const mpd_t *b, uint32_t *status); static inline void _mpd_qpow_uint(mpd_t *result, mpd_t *base, mpd_uint_t exp, uint8_t resultsign, const mpd_context_t *ctx, uint32_t *status); @@ -3256,6 +3256,20 @@ mpd_qfinalize(result, ctx, status); } +/* Add a and b. Set NaN/Invalid_operation if the result is inexact. */ +static void +_mpd_qadd_exact(mpd_t *result, const mpd_t *a, const mpd_t *b, + const mpd_context_t *ctx, uint32_t *status) +{ + uint32_t workstatus = 0; + + mpd_qadd(result, a, b, ctx, &workstatus); + *status |= workstatus; + if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) { + mpd_seterror(result, MPD_Invalid_operation, status); + } +} + /* Subtract b from a. */ void mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b, @@ -3273,6 +3287,20 @@ mpd_qfinalize(result, ctx, status); } +/* Subtract b from a. Set NaN/Invalid_operation if the result is inexact. */ +static void +_mpd_qsub_exact(mpd_t *result, const mpd_t *a, const mpd_t *b, + const mpd_context_t *ctx, uint32_t *status) +{ + uint32_t workstatus = 0; + + mpd_qsub(result, a, b, ctx, &workstatus); + *status |= workstatus; + if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) { + mpd_seterror(result, MPD_Invalid_operation, status); + } +} + /* Add decimal and mpd_ssize_t. */ void mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, @@ -3500,7 +3528,7 @@ } else { MPD_NEW_STATIC(r,0,0,0,0); - _mpd_qbarrett_divmod(q, &r, a, b, status); + _mpd_base_ndivmod(q, &r, a, b, status); if (mpd_isspecial(q) || mpd_isspecial(&r)) { mpd_del(&r); goto finish; @@ -3652,14 +3680,10 @@ } } else { - _mpd_qbarrett_divmod(q, r, a, b, status); + _mpd_base_ndivmod(q, r, a, b, status); if (mpd_isspecial(q) || mpd_isspecial(r)) { goto nanresult; } - if (mpd_isinfinite(q) || q->digits > ctx->prec) { - *status |= MPD_Division_impossible; - goto nanresult; - } qsize = q->len; rsize = r->len; } @@ -5369,6 +5393,20 @@ mpd_qfinalize(result, ctx, status); } +/* Multiply a and b. Set NaN/Invalid_operation if the result is inexact. */ +static void +_mpd_qmul_exact(mpd_t *result, const mpd_t *a, const mpd_t *b, + const mpd_context_t *ctx, uint32_t *status) +{ + uint32_t workstatus = 0; + + mpd_qmul(result, a, b, ctx, &workstatus); + *status |= workstatus; + if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) { + mpd_seterror(result, MPD_Invalid_operation, status); + } +} + /* Multiply decimal and mpd_ssize_t. */ void mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, @@ -6691,11 +6729,18 @@ return i-1; } -/* Initial approximation for the reciprocal. */ +/* + * Initial approximation for the reciprocal: + * k_0 := MPD_RDIGITS-2 + * z_0 := 10**(-k_0) * floor(10**(2*k_0 + 2) / floor(v * 10**(k_0 + 2))) + * Absolute error: + * |1/v - z_0| < 10**(-k_0) + * ACL2 proof: maxerror-inverse-approx + */ static void _mpd_qreciprocal_approx(mpd_t *z, const mpd_t *v, uint32_t *status) { - mpd_uint_t p10data[2] = {0, mpd_pow10[MPD_RDIGITS-2]}; /* 10**(2*MPD_RDIGITS-2) */ + mpd_uint_t p10data[2] = {0, mpd_pow10[MPD_RDIGITS-2]}; mpd_uint_t dummy, word; int n; @@ -6714,7 +6759,12 @@ mpd_setdigits(z); } -/* Reciprocal, calculated with Newton's Method. Assumption: result != a. */ +/* + * Reciprocal, calculated with Newton's Method. Assumption: result != a. + * NOTE: The comments in the function show that certain operations are + * exact. The proof for the maximum error is too long to fit in here. + * ACL2 proof: maxerror-inverse-complete + */ static void _mpd_qreciprocal(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status) @@ -6738,32 +6788,43 @@ adj = v->digits + v->exp; v->exp = -v->digits; - /* initial approximation */ + /* Initial approximation */ _mpd_qreciprocal_approx(z, v, status); mpd_maxcontext(&varcontext); mpd_maxcontext(&maxcontext); - varcontext.round = MPD_ROUND_TRUNC; - maxcontext.round = MPD_ROUND_TRUNC; - - maxprec = (v->digits > ctx->prec) ? v->digits : ctx->prec; + varcontext.round = maxcontext.round = MPD_ROUND_TRUNC; + varcontext.emax = maxcontext.emax = MPD_MAX_EMAX + 100; + varcontext.emin = maxcontext.emin = MPD_MIN_EMIN - 100; + maxcontext.prec = MPD_MAX_PREC + 100; + + maxprec = ctx->prec; maxprec += 2; initprec = MPD_RDIGITS-3; i = recpr_schedule_prec(klist, maxprec, initprec); for (; i >= 0; i--) { - mpd_qmul(&s, z, z, &maxcontext, status); + /* Loop invariant: z->digits <= klist[i]+7 */ + /* Let s := z**2, exact result */ + _mpd_qmul_exact(&s, z, z, &maxcontext, status); varcontext.prec = 2*klist[i] + 5; if (v->digits > varcontext.prec) { + /* Let t := v, truncated to n >= 2*k+5 fraction digits */ mpd_qshiftr(&t, v, v->digits-varcontext.prec, status); t.exp = -varcontext.prec; + /* Let t := trunc(v)*s, truncated to n >= 2*k+1 fraction digits */ mpd_qmul(&t, &t, &s, &varcontext, status); } - else { + else { /* v->digits <= 2*k+5 */ + /* Let t := v*s, truncated to n >= 2*k+1 fraction digits */ mpd_qmul(&t, v, &s, &varcontext, status); } - mpd_qmul(&s, z, &two, &maxcontext, status); - mpd_qsub(z, &s, &t, &maxcontext, status); + /* Let s := 2*z, exact result */ + _mpd_qmul_exact(&s, z, &two, &maxcontext, status); + /* s.digits < t.digits <= 2*k+5, |adjexp(s)-adjexp(t)| <= 1, + * so the subtraction generates at most 2*k+6 <= klist[i+1]+7 + * digits. The loop invariant is preserved. */ + _mpd_qsub_exact(z, &s, &t, &maxcontext, status); } if (!mpd_isspecial(z)) { @@ -6777,22 +6838,29 @@ } /* - * Integer division with remainder of the coefficients: coeff(a) / coeff(b). - * This function is for large numbers where it is faster to divide by - * multiplying the dividend by the reciprocal of the divisor. - * The inexact result is fixed by a small loop, which should not take - * more than 2 iterations. + * Internal function for large numbers: + * + * q, r = divmod(coeff(a), coeff(b)) + * + * Strategy: Multiply the dividend by the reciprocal of the divisor. The + * inexact result is fixed by a small loop, using at most 2 iterations. + * + * ACL2 proofs: + * ------------ + * 1) q is a natural number. (ndivmod-quotient-natp) + * 2) r is a natural number. (ndivmod-remainder-natp) + * 3) a = q * b + r (ndivmod-q*b+r==a) + * 4) r < b (ndivmod-remainder-<-b) */ static void -_mpd_qbarrett_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, - uint32_t *status) +_mpd_base_ndivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, + uint32_t *status) { mpd_context_t workctx; mpd_t *qq = q, *rr = r; mpd_t aa, bb; int k; - mpd_maxcontext(&workctx); _mpd_copy_shared(&aa, a); _mpd_copy_shared(&bb, b); @@ -6814,41 +6882,68 @@ } } - /* maximum length of q + 3 digits */ - workctx.prec = aa.digits - bb.digits + 1 + 3; - /* we get the reciprocal with precision maxlen(q) + 3 */ + mpd_maxcontext(&workctx); + + /* Let prec := adigits - bdigits + 4 */ + workctx.prec = a->digits - b->digits + 1 + 3; + if (a->digits > MPD_MAX_PREC || workctx.prec > MPD_MAX_PREC) { + *status |= MPD_Division_impossible; + goto nanresult; + } + + /* Let x := _mpd_qreciprocal(b, prec) + * Then x is bounded by: + * 1) 1/b - 10**(-prec - bdigits) < x < 1/b + 10**(-prec - bdigits) + * 2) 1/b - 10**(-adigits - 4) < x < 1/b + 10**(-adigits - 4) + */ _mpd_qreciprocal(rr, &bb, &workctx, &workctx.status); - mpd_qmul(qq, &aa, rr, &workctx, &workctx.status); + /* Get an estimate for the quotient. Let q := a * x + * Then q is bounded by: + * 3) a/b - 10**-4 < q < a/b + 10**-4 + */ + _mpd_qmul(qq, &aa, rr, &workctx, &workctx.status); + /* Truncate q to an integer: + * 4) a/b - 2 < trunc(q) < a/b + 1 + */ mpd_qtrunc(qq, qq, &workctx, &workctx.status); workctx.prec = aa.digits + 3; - /* get the remainder */ - mpd_qmul(rr, &bb, qq, &workctx, &workctx.status); - mpd_qsub(rr, &aa, rr, &workctx, &workctx.status); - - /* Fix the result. Algorithm from: Karl Hasselstrom, Fast Division of Large Integers */ + workctx.emax = MPD_MAX_EMAX + 3; + workctx.emin = MPD_MIN_EMIN - 3; + /* Multiply the estimate for q by b: + * 5) a - 2 * b < trunc(q) * b < a + b + */ + _mpd_qmul(rr, &bb, qq, &workctx, &workctx.status); + /* Get the estimate for r such that a = q * b + r. */ + _mpd_qsub_exact(rr, &aa, rr, &workctx, &workctx.status); + + /* Fix the result. At this point -b < r < 2*b, so the correction loop + takes at most one iteration. */ for (k = 0;; k++) { - if (mpd_isspecial(rr)) { + if (mpd_isspecial(qq) || mpd_isspecial(rr)) { *status |= (workctx.status&MPD_Errors); goto nanresult; } - if (k > 2) { - mpd_err_warn("libmpdec: internal error in " /* GCOV_NOT_REACHED */ - "_mpd_qbarrett_divmod: please report"); /* GCOV_NOT_REACHED */ - *status |= MPD_Invalid_operation; /* GCOV_NOT_REACHED */ - goto nanresult; /* GCOV_NOT_REACHED */ - } + if (k > 2) { /* Allow two iterations despite the proof. */ + mpd_err_warn("libmpdec: internal error in " /* GCOV_NOT_REACHED */ + "_mpd_base_ndivmod: please report"); /* GCOV_NOT_REACHED */ + *status |= MPD_Invalid_operation; /* GCOV_NOT_REACHED */ + goto nanresult; /* GCOV_NOT_REACHED */ + } + /* r < 0 */ else if (_mpd_cmp(&zero, rr) == 1) { - mpd_qadd(rr, rr, &bb, &workctx, &workctx.status); - mpd_qadd(qq, qq, &minus_one, &workctx, &workctx.status); - } + _mpd_qadd_exact(rr, rr, &bb, &workctx, &workctx.status); + _mpd_qadd_exact(qq, qq, &minus_one, &workctx, &workctx.status); + } + /* 0 <= r < b */ else if (_mpd_cmp(rr, &bb) == -1) { break; } + /* r >= b */ else { - mpd_qsub(rr, rr, &bb, &workctx, &workctx.status); - mpd_qadd(qq, qq, &one, &workctx, &workctx.status); + _mpd_qsub_exact(rr, rr, &bb, &workctx, &workctx.status); + _mpd_qadd_exact(qq, qq, &one, &workctx, &workctx.status); } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 21:02:24 2012 From: python-checkins at python.org (stefan.krah) Date: Fri, 20 Apr 2012 21:02:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Defensive_programming=3A_mp?= =?utf8?q?d=5Fisspecial=28r=29_already_implies_mpd=5Fisspecial=28q=29=2C_b?= =?utf8?q?ut?= Message-ID: http://hg.python.org/cpython/rev/a3d7cfff3688 changeset: 76433:a3d7cfff3688 user: Stefan Krah date: Fri Apr 20 21:00:31 2012 +0200 summary: Defensive programming: mpd_isspecial(r) already implies mpd_isspecial(q), but this is more readable. files: Modules/_decimal/libmpdec/mpdecimal.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -3530,6 +3530,7 @@ MPD_NEW_STATIC(r,0,0,0,0); _mpd_base_ndivmod(q, &r, a, b, status); if (mpd_isspecial(q) || mpd_isspecial(&r)) { + mpd_setspecial(q, MPD_POS, MPD_NAN); mpd_del(&r); goto finish; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 21:23:17 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 21:23:17 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314599=3A_Generaliz?= =?utf8?q?e_a_test_for_ImportError=2Epath_and_add_support?= Message-ID: http://hg.python.org/cpython/rev/573010778eed changeset: 76434:573010778eed parent: 76432:8f0307550f5a user: Brett Cannon date: Fri Apr 20 15:22:50 2012 -0400 summary: Issue #14599: Generalize a test for ImportError.path and add support in Python/dynload_shlibs.c. This should fix the remaining importlib test failure on Windows. Support in AIX and HP-UX will be in a separate checkin. files: Lib/test/test_imp.py | 11 +++++++++++ Lib/test/test_import.py | 22 ---------------------- Python/dynload_shlib.c | 11 ++++++++++- Python/importdl.c | 9 +++++---- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -179,6 +179,17 @@ self.assertRaises(SyntaxError, imp.find_module, "badsyntax_pep3120", [path]) + def test_load_dynamic_ImportError_path(self): + # Issue #1559549 added `name` and `path` attributes to ImportError + # in order to provide better detail. Issue #10854 implemented those + # attributes on import failures of extensions on Windows. + path = 'bogus file path' + name = 'extension' + with self.assertRaises(ImportError) as err: + imp.load_dynamic(name, path) + self.assertIn(path, err.exception.path) + self.assertEqual(name, err.exception.name) + class ReloadTests(unittest.TestCase): diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -337,28 +337,6 @@ del sys.path[0] remove_files(TESTFN) - @unittest.skipUnless(sys.platform == "win32", "Windows-specific") - def test_extension_import_fail(self): - # Issue 1559549 added `name` and `path` attributes to ImportError - # in order to provide better detail. Issue 10854 implemented those - # attributes on import failures of extensions on Windows. - debug = True if sys.executable[-6:] == "_d.exe" else False - pkg_name = "extension" - pkg_file = pkg_name + "{}".format("_d.pyd" if debug else ".pyd") - with open(pkg_file, "w"): pass - importlib.invalidate_caches() - try: - with self.assertRaises(ImportError) as err: - import extension - self.assertEqual(err.exception.name, pkg_name) - # The path we get back has the dot-slash, e.g., ".\\extension.pyd" - self.assertIsNotNone(err.exception.path, - 'unexpected None for ImportError.path: ' - '{!r}'.format(err.exception)) - self.assertEqual(os.path.relpath(err.exception.path), pkg_file) - finally: - unlink(pkg_file) - class PycRewritingTests(unittest.TestCase): # Test that the `co_filename` attribute on code objects always points diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -129,10 +129,19 @@ handle = dlopen(pathname, dlopenflags); if (handle == NULL) { + PyObject *mod_name = NULL; + PyObject *path = NULL; + PyObject *error_ob = NULL; const char *error = dlerror(); if (error == NULL) error = "unknown dlopen() error"; - PyErr_SetString(PyExc_ImportError, error); + error_ob = PyUnicode_FromString(error); + path = PyUnicode_FromString(pathname); + mod_name = PyUnicode_FromString(shortname); + PyErr_SetImportError(error_ob, mod_name, path); + Py_DECREF(error_ob); + Py_DECREF(path); + Py_DECREF(mod_name); return NULL; } if (fp != NULL && nhandles < 128) diff --git a/Python/importdl.c b/Python/importdl.c --- a/Python/importdl.c +++ b/Python/importdl.c @@ -74,10 +74,11 @@ if (PyErr_Occurred()) goto error; if (p == NULL) { - PyErr_Format(PyExc_ImportError, - "dynamic module does not define init function" - " (PyInit_%s)", - shortname); + PyObject *msg = PyUnicode_FromFormat("dynamic module does not define " + "init function (PyInit_%s)", + shortname); + PyErr_SetImportError(msg, name, path); + Py_DECREF(msg); goto error; } oldcontext = _Py_PackageContext; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 21:23:18 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 21:23:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/9943bdbbe09c changeset: 76435:9943bdbbe09c parent: 76434:573010778eed parent: 76433:a3d7cfff3688 user: Brett Cannon date: Fri Apr 20 15:23:11 2012 -0400 summary: merge files: Modules/_decimal/libmpdec/mpdecimal.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -3530,6 +3530,7 @@ MPD_NEW_STATIC(r,0,0,0,0); _mpd_base_ndivmod(q, &r, a, b, status); if (mpd_isspecial(q) || mpd_isspecial(&r)) { + mpd_setspecial(q, MPD_POS, MPD_NAN); mpd_del(&r); goto finish; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 21:31:18 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 21:31:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314599=3A_Support_I?= =?utf8?q?mportError=2Epath_on_AIX_and_HPUX_when_loading?= Message-ID: http://hg.python.org/cpython/rev/56aa4cda11a8 changeset: 76436:56aa4cda11a8 user: Brett Cannon date: Fri Apr 20 15:31:11 2012 -0400 summary: Issue #14599: Support ImportError.path on AIX and HPUX when loading extension modules. files: Python/dynload_aix.c | 8 +++++++- Python/dynload_hpux.c | 12 +++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Python/dynload_aix.c b/Python/dynload_aix.c --- a/Python/dynload_aix.c +++ b/Python/dynload_aix.c @@ -108,6 +108,8 @@ { char *message[1024], errbuf[1024]; + PyObject *pathname_ob = NULL; + PyObject *errbuf_ob = NULL; register int i,j; struct errtab { @@ -147,7 +149,11 @@ ERRBUF_APPEND("\n"); } errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */ - PyErr_SetString(PyExc_ImportError, errbuf); + pathname_ob = PyUnicode_FromString(pathname); + errbuf_ob = PyUnicode_FromString(errbuf); + PyErr_SetImportError(errbuf_ob, NULL, pathname); + Py_DECREF(pathname_ob); + Py_DECREF(errbuf_ob); return; } diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -36,11 +36,21 @@ /* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */ if (lib == NULL) { char buf[256]; + PyObject *pathname_ob = NULL; + PyObject *buf_ob = NULL; + PyObject *shortname_ob = NULL; + if (Py_VerboseFlag) perror(pathname); PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s", pathname); - PyErr_SetString(PyExc_ImportError, buf); + buf_ob = PyUnicode_FromString(buf); + shortname_ob = PyUnicode_FromString(shortname); + pathname_ob = PyUnicode_FromString(pathname); + PyErr_SetImportError(buf_ob, shortname_ob, pathname_ob); + Py_DECREF(buf_ob); + Py_DECREF(shortname_ob); + Py_DECREF(pathname_ob); return NULL; } PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, shortname); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 21:52:22 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 21:52:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314585=3A_test=5Fim?= =?utf8?q?port_now_runs_all_tests_under?= Message-ID: http://hg.python.org/cpython/rev/a74ba7407457 changeset: 76437:a74ba7407457 user: Brett Cannon date: Fri Apr 20 15:52:17 2012 -0400 summary: Issue #14585: test_import now runs all tests under importlib.test.import_ using builtins.__import__() instead of just the relative import tests. files: Lib/importlib/test/__init__.py | 25 ++++++++++++++++++++++ Lib/test/test_import.py | 25 ++++++++------------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/Lib/importlib/test/__init__.py b/Lib/importlib/test/__init__.py --- a/Lib/importlib/test/__init__.py +++ b/Lib/importlib/test/__init__.py @@ -0,0 +1,25 @@ +import os +import sys +import unittest + +def test_suite(package=__package__, directory=os.path.dirname(__file__)): + suite = unittest.TestSuite() + for name in os.listdir(directory): + if name.startswith(('.', '__')): + continue + path = os.path.join(directory, name) + if (os.path.isfile(path) and name.startswith('test_') and + name.endswith('.py')): + submodule_name = os.path.splitext(name)[0] + module_name = "{0}.{1}".format(package, submodule_name) + __import__(module_name, level=0) + module_tests = unittest.findTestCases(sys.modules[module_name]) + suite.addTest(module_tests) + elif os.path.isdir(path): + package_name = "{0}.{1}".format(package, name) + __import__(package_name, level=0) + package_tests = getattr(sys.modules[package_name], 'test_suite')() + suite.addTest(package_tests) + else: + continue + return suite diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -1,6 +1,6 @@ import builtins import imp -from importlib.test.import_ import test_relative_imports +from importlib.test.import_ import test_suite as importlib_import_test_suite from importlib.test.import_ import util as importlib_util import importlib import marshal @@ -694,21 +694,16 @@ self.assertEqual(m.x, 5) -class RelativeImportFromImportlibTests(test_relative_imports.RelativeImports): - - def setUp(self): - self._importlib_util_flag = importlib_util.using___import__ +def test_main(verbose=None): + flag = importlib_util.using___import__ + try: importlib_util.using___import__ = True - - def tearDown(self): - importlib_util.using___import__ = self._importlib_util_flag - - -def test_main(verbose=None): - run_unittest(ImportTests, PycacheTests, - PycRewritingTests, PathsTests, RelativeImportTests, - OverridingImportBuiltinTests, - RelativeImportFromImportlibTests) + run_unittest(ImportTests, PycacheTests, + PycRewritingTests, PathsTests, RelativeImportTests, + OverridingImportBuiltinTests, + importlib_import_test_suite()) + finally: + importlib_util.using___import__ = flag if __name__ == '__main__': -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 21:58:03 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 21:58:03 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314628=3A_Document_?= =?utf8?q?the_fact_that_import_always_returns_the_module?= Message-ID: http://hg.python.org/cpython/rev/150bd84e737e changeset: 76438:150bd84e737e user: Brett Cannon date: Fri Apr 20 15:57:46 2012 -0400 summary: Issue #14628: Document the fact that import always returns the module as found in sys.modules and not as what the loader returns (even though it is required to by PEP 302). files: Doc/reference/simple_stmts.rst | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -776,7 +776,8 @@ be set to the name of package that contains the module or package (the empty string is used for module not contained in a package). :data:`__loader__` is also optional but should be set to the loader object that is loading the -module. +module. While loaders are required to return the module they loaded, import +itself always retrieves any modules it returns from :data:`sys.modules`. .. index:: exception: ImportError -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 22:21:46 2012 From: python-checkins at python.org (mark.dickinson) Date: Fri, 20 Apr 2012 22:21:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314339=3A_Improve_s?= =?utf8?q?peed_of_bin=2C_oct_and_hex_builtins=2E__Patch_by_Serhiy?= Message-ID: http://hg.python.org/cpython/rev/dcd3344b6d5b changeset: 76439:dcd3344b6d5b user: Mark Dickinson date: Fri Apr 20 21:21:24 2012 +0100 summary: Issue #14339: Improve speed of bin, oct and hex builtins. Patch by Serhiy Storchaka (with minor modifications). files: Misc/NEWS | 3 + Objects/longobject.c | 61 +++++++++++++++++-------------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14339: Speed improvements to bin, oct and hex functions. Patch by + Serhiy Storchaka. + - Issue #14098: New functions PyErr_GetExcInfo and PyErr_SetExcInfo. Patch by Stefan Behnel. diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1672,11 +1672,10 @@ { register PyLongObject *a = (PyLongObject *)aa; PyObject *v; - Py_ssize_t i, sz; + Py_ssize_t sz; Py_ssize_t size_a; - char *p; - char sign = '\0'; - char *buffer; + Py_UCS1 *p; + int negative; int bits; assert(base == 2 || base == 8 || base == 10 || base == 16); @@ -1688,6 +1687,7 @@ return NULL; } size_a = ABS(Py_SIZE(a)); + negative = Py_SIZE(a) < 0; /* Compute a rough upper bound for the length of the string */ switch (base) { @@ -1704,33 +1704,40 @@ assert(0); /* shouldn't ever get here */ bits = 0; /* to silence gcc warning */ } - /* compute length of output string: allow 2 characters for prefix and - 1 for possible '-' sign. */ - if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT / sizeof(Py_UCS4)) { - PyErr_SetString(PyExc_OverflowError, - "int is too large to format"); + + /* Compute exact length 'sz' of output string. */ + if (size_a == 0) { + sz = 3; + } + else { + Py_ssize_t size_a_in_bits; + /* Ensure overflow doesn't occur during computation of sz. */ + if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT) { + PyErr_SetString(PyExc_OverflowError, + "int is too large to format"); + return NULL; + } + size_a_in_bits = (size_a - 1) * PyLong_SHIFT + + bits_in_digit(a->ob_digit[size_a - 1]); + /* Allow 2 characters for prefix and 1 for a '-' sign. */ + sz = 2 + negative + (size_a_in_bits + (bits - 1)) / bits; + } + + v = PyUnicode_New(sz, 'x'); + if (v == NULL) { return NULL; } - /* now size_a * PyLong_SHIFT + 3 <= PY_SSIZE_T_MAX, so the RHS below - is safe from overflow */ - sz = 3 + (size_a * PyLong_SHIFT + (bits - 1)) / bits; - assert(sz >= 0); - buffer = PyMem_Malloc(sz); - if (buffer == NULL) { - PyErr_NoMemory(); - return NULL; - } - p = &buffer[sz]; - if (Py_SIZE(a) < 0) - sign = '-'; - - if (Py_SIZE(a) == 0) { + assert(PyUnicode_KIND(v) == PyUnicode_1BYTE_KIND); + + p = PyUnicode_1BYTE_DATA(v) + sz; + if (size_a == 0) { *--p = '0'; } else { /* JRH: special case for power-of-2 bases */ twodigits accum = 0; int accumbits = 0; /* # of bits in accum */ + Py_ssize_t i; for (i = 0; i < size_a; ++i) { accum |= (twodigits)a->ob_digit[i] << accumbits; accumbits += PyLong_SHIFT; @@ -1739,7 +1746,6 @@ char cdigit; cdigit = (char)(accum & (base - 1)); cdigit += (cdigit < 10) ? '0' : 'a'-10; - assert(p > buffer); *--p = cdigit; accumbits -= bits; accum >>= bits; @@ -1754,10 +1760,9 @@ else /* (base == 2) */ *--p = 'b'; *--p = '0'; - if (sign) - *--p = sign; - v = PyUnicode_DecodeASCII(p, &buffer[sz] - p, NULL); - PyMem_Free(buffer); + if (negative) + *--p = '-'; + assert(p == PyUnicode_1BYTE_DATA(v)); return v; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 22:44:30 2012 From: python-checkins at python.org (mark.dickinson) Date: Fri, 20 Apr 2012 22:44:30 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NjMw?= =?utf8?q?=3A_Fix_an_incorrect_access_of_ob=5Fdigit=5B0=5D_for_a_zero_inst?= =?utf8?q?ance_of_an?= Message-ID: http://hg.python.org/cpython/rev/cdcc6b489862 changeset: 76440:cdcc6b489862 branch: 3.2 parent: 76425:b07488490001 user: Mark Dickinson date: Fri Apr 20 21:42:49 2012 +0100 summary: Issue #14630: Fix an incorrect access of ob_digit[0] for a zero instance of an int subclass. files: Lib/test/test_long.py | 14 ++++++++++++++ Misc/NEWS | 3 +++ Objects/longobject.c | 4 +--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -1148,6 +1148,20 @@ self.assertRaises(TypeError, myint.from_bytes, 0, 'big') self.assertRaises(TypeError, int.from_bytes, 0, 'big', True) + def test_access_to_nonexistent_digit_0(self): + # http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that + # ob_digit[0] was being incorrectly accessed for instances of a + # subclass of int, with value 0. + class Integer(int): + def __new__(cls, value=0): + self = int.__new__(cls, value) + self.foo = 'foo' + return self + + integers = [Integer(0) for i in range(1000)] + for n in map(int, integers): + self.assertEqual(n, 0) + def test_main(): support.run_unittest(LongTest) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14630: Fix a memory access bug for instances of a subclass of int + with value 0. + - Issue #14612: Fix jumping around with blocks by setting f_lineno. - Issue #14607: Fix keyword-only arguments which started with ``__``. diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -156,9 +156,7 @@ if (i < 0) i = -(i); if (i < 2) { - sdigit ival = src->ob_digit[0]; - if (Py_SIZE(src) < 0) - ival = -ival; + sdigit ival = MEDIUM_VALUE(src); CHECK_SMALL_INT(ival); } result = _PyLong_New(i); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 22:44:31 2012 From: python-checkins at python.org (mark.dickinson) Date: Fri, 20 Apr 2012 22:44:31 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314630=3A_Merge_fix_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/c7b0f711dc15 changeset: 76441:c7b0f711dc15 parent: 76439:dcd3344b6d5b parent: 76440:cdcc6b489862 user: Mark Dickinson date: Fri Apr 20 21:44:09 2012 +0100 summary: Issue #14630: Merge fix from 3.2. files: Lib/test/test_long.py | 14 ++++++++++++++ Misc/NEWS | 3 +++ Objects/longobject.c | 4 +--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -1228,6 +1228,20 @@ self.assertRaises(TypeError, myint.from_bytes, 0, 'big') self.assertRaises(TypeError, int.from_bytes, 0, 'big', True) + def test_access_to_nonexistent_digit_0(self): + # http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that + # ob_digit[0] was being incorrectly accessed for instances of a + # subclass of int, with value 0. + class Integer(int): + def __new__(cls, value=0): + self = int.__new__(cls, value) + self.foo = 'foo' + return self + + integers = [Integer(0) for i in range(1000)] + for n in map(int, integers): + self.assertEqual(n, 0) + def test_main(): support.run_unittest(LongTest) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14630: Fix a memory access bug for instances of a subclass of int + with value 0. + - Issue #14339: Speed improvements to bin, oct and hex functions. Patch by Serhiy Storchaka. diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -156,9 +156,7 @@ if (i < 0) i = -(i); if (i < 2) { - sdigit ival = src->ob_digit[0]; - if (Py_SIZE(src) < 0) - ival = -ival; + sdigit ival = MEDIUM_VALUE(src); CHECK_SMALL_INT(ival); } result = _PyLong_New(i); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 23:19:21 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 23:19:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Use_a_skipUnless_decorator_?= =?utf8?q?instead_of_conditional_renaming=2E?= Message-ID: http://hg.python.org/cpython/rev/b863d7dd113c changeset: 76442:b863d7dd113c parent: 76438:150bd84e737e user: Brett Cannon date: Fri Apr 20 16:29:39 2012 -0400 summary: Use a skipUnless decorator instead of conditional renaming. files: Lib/test/test_import.py | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -455,6 +455,7 @@ unload("test_trailing_slash") # Regression test for http://bugs.python.org/issue3677. + @unittest.skipUnless(sys.platform == 'win32', 'Windows-specific') def _test_UNC_path(self): with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f: f.write("testdata = 'test_trailing_slash'") @@ -470,9 +471,6 @@ self.assertEqual(mod.testdata, 'test_trailing_slash') unload("test_trailing_slash") - if sys.platform == "win32": - test_UNC_path = _test_UNC_path - class RelativeImportTests(unittest.TestCase): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 23:19:22 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 23:19:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_Merge?= Message-ID: http://hg.python.org/cpython/rev/f5a5b2f5c7ef changeset: 76443:f5a5b2f5c7ef parent: 76442:b863d7dd113c parent: 76441:c7b0f711dc15 user: Brett Cannon date: Fri Apr 20 17:19:14 2012 -0400 summary: Merge files: Lib/test/test_long.py | 14 ++++++ Misc/NEWS | 6 ++ Objects/longobject.c | 65 ++++++++++++++++-------------- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -1228,6 +1228,20 @@ self.assertRaises(TypeError, myint.from_bytes, 0, 'big') self.assertRaises(TypeError, int.from_bytes, 0, 'big', True) + def test_access_to_nonexistent_digit_0(self): + # http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that + # ob_digit[0] was being incorrectly accessed for instances of a + # subclass of int, with value 0. + class Integer(int): + def __new__(cls, value=0): + self = int.__new__(cls, value) + self.foo = 'foo' + return self + + integers = [Integer(0) for i in range(1000)] + for n in map(int, integers): + self.assertEqual(n, 0) + def test_main(): support.run_unittest(LongTest) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,12 @@ Core and Builtins ----------------- +- Issue #14630: Fix a memory access bug for instances of a subclass of int + with value 0. + +- Issue #14339: Speed improvements to bin, oct and hex functions. Patch by + Serhiy Storchaka. + - Issue #14098: New functions PyErr_GetExcInfo and PyErr_SetExcInfo. Patch by Stefan Behnel. diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -156,9 +156,7 @@ if (i < 0) i = -(i); if (i < 2) { - sdigit ival = src->ob_digit[0]; - if (Py_SIZE(src) < 0) - ival = -ival; + sdigit ival = MEDIUM_VALUE(src); CHECK_SMALL_INT(ival); } result = _PyLong_New(i); @@ -1672,11 +1670,10 @@ { register PyLongObject *a = (PyLongObject *)aa; PyObject *v; - Py_ssize_t i, sz; + Py_ssize_t sz; Py_ssize_t size_a; - char *p; - char sign = '\0'; - char *buffer; + Py_UCS1 *p; + int negative; int bits; assert(base == 2 || base == 8 || base == 10 || base == 16); @@ -1688,6 +1685,7 @@ return NULL; } size_a = ABS(Py_SIZE(a)); + negative = Py_SIZE(a) < 0; /* Compute a rough upper bound for the length of the string */ switch (base) { @@ -1704,33 +1702,40 @@ assert(0); /* shouldn't ever get here */ bits = 0; /* to silence gcc warning */ } - /* compute length of output string: allow 2 characters for prefix and - 1 for possible '-' sign. */ - if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT / sizeof(Py_UCS4)) { - PyErr_SetString(PyExc_OverflowError, - "int is too large to format"); + + /* Compute exact length 'sz' of output string. */ + if (size_a == 0) { + sz = 3; + } + else { + Py_ssize_t size_a_in_bits; + /* Ensure overflow doesn't occur during computation of sz. */ + if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT) { + PyErr_SetString(PyExc_OverflowError, + "int is too large to format"); + return NULL; + } + size_a_in_bits = (size_a - 1) * PyLong_SHIFT + + bits_in_digit(a->ob_digit[size_a - 1]); + /* Allow 2 characters for prefix and 1 for a '-' sign. */ + sz = 2 + negative + (size_a_in_bits + (bits - 1)) / bits; + } + + v = PyUnicode_New(sz, 'x'); + if (v == NULL) { return NULL; } - /* now size_a * PyLong_SHIFT + 3 <= PY_SSIZE_T_MAX, so the RHS below - is safe from overflow */ - sz = 3 + (size_a * PyLong_SHIFT + (bits - 1)) / bits; - assert(sz >= 0); - buffer = PyMem_Malloc(sz); - if (buffer == NULL) { - PyErr_NoMemory(); - return NULL; - } - p = &buffer[sz]; - if (Py_SIZE(a) < 0) - sign = '-'; - - if (Py_SIZE(a) == 0) { + assert(PyUnicode_KIND(v) == PyUnicode_1BYTE_KIND); + + p = PyUnicode_1BYTE_DATA(v) + sz; + if (size_a == 0) { *--p = '0'; } else { /* JRH: special case for power-of-2 bases */ twodigits accum = 0; int accumbits = 0; /* # of bits in accum */ + Py_ssize_t i; for (i = 0; i < size_a; ++i) { accum |= (twodigits)a->ob_digit[i] << accumbits; accumbits += PyLong_SHIFT; @@ -1739,7 +1744,6 @@ char cdigit; cdigit = (char)(accum & (base - 1)); cdigit += (cdigit < 10) ? '0' : 'a'-10; - assert(p > buffer); *--p = cdigit; accumbits -= bits; accum >>= bits; @@ -1754,10 +1758,9 @@ else /* (base == 2) */ *--p = 'b'; *--p = '0'; - if (sign) - *--p = sign; - v = PyUnicode_DecodeASCII(p, &buffer[sz] - p, NULL); - PyMem_Free(buffer); + if (negative) + *--p = '-'; + assert(p == PyUnicode_1BYTE_DATA(v)); return v; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 20 23:35:04 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Apr 2012 23:35:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_a_cleanup=2E?= Message-ID: http://hg.python.org/cpython/rev/a8484e56811b changeset: 76444:a8484e56811b user: Brett Cannon date: Fri Apr 20 17:34:59 2012 -0400 summary: Fix a cleanup. files: Lib/test/test_import.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -456,7 +456,7 @@ # Regression test for http://bugs.python.org/issue3677. @unittest.skipUnless(sys.platform == 'win32', 'Windows-specific') - def _test_UNC_path(self): + def test_UNC_path(self): with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f: f.write("testdata = 'test_trailing_slash'") # Create the UNC path, like \\myhost\c$\foo\bar. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 21 00:04:11 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 21 Apr 2012 00:04:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Keep_imp?= =?utf8?q?=2Eget=5Fmagic=28=29_in_C_code=2C_but_cache_in_importlib?= Message-ID: http://hg.python.org/cpython/rev/c820aa9c0c00 changeset: 76445:c820aa9c0c00 user: Brett Cannon date: Fri Apr 20 18:04:03 2012 -0400 summary: Issue #13959: Keep imp.get_magic() in C code, but cache in importlib for performance. While get_magic() could move to Lib/imp.py, having to support PyImport_GetMagicNumber() would lead to equal, if not more, C code than sticking with the status quo. files: Lib/imp.py | 4 +++- Lib/importlib/_bootstrap.py | 12 ++++++++---- Python/importlib.h | Bin 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -11,8 +11,10 @@ init_builtin, init_frozen, is_builtin, is_frozen, _fix_co_filename) # Can (probably) move to importlib -from _imp import (get_magic, get_tag, get_suffixes, cache_from_source, +from _imp import (get_tag, get_suffixes, cache_from_source, source_from_cache) +# Could move out of _imp, but not worth the code +from _imp import get_magic # Should be re-implemented here (and mostly deprecated) from _imp import (find_module, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -401,9 +401,9 @@ magic = data[:4] raw_timestamp = data[4:8] raw_size = data[8:12] - if len(magic) != 4 or magic != _imp.get_magic(): - raise ImportError("bad magic number in {}".format(fullname), - name=fullname, path=bytecode_path) + if magic != _MAGIC_NUMBER: + msg = 'bad magic number in {!r}: {!r}'.format(fullname, magic) + raise ImportError(msg, name=fullname, path=bytecode_path) elif len(raw_timestamp) != 4: message = 'bad timestamp in {}'.format(fullname) verbose_message(message) @@ -549,7 +549,7 @@ # If e.g. Jython ever implements imp.cache_from_source to have # their own cached file format, this block of code will most likely # throw an exception. - data = bytearray(_imp.get_magic()) + data = bytearray(_MAGIC_NUMBER) data.extend(_w_long(source_mtime)) data.extend(_w_long(len(source_bytes))) data.extend(marshal.dumps(code_object)) @@ -1115,6 +1115,9 @@ return _handle_fromlist(module, fromlist, _gcd_import) +_MAGIC_NUMBER = None # Set in _setup() + + def _setup(sys_module, _imp_module): """Setup importlib by importing needed built-in modules and injecting them into the global namespace. @@ -1158,6 +1161,7 @@ setattr(self_module, 'path_sep', path_sep) # Constants setattr(self_module, '_relax_case', _make_relax_case()) + setattr(self_module, '_MAGIC_NUMBER', _imp_module.get_magic()) def _install(sys_module, _imp_module): diff --git a/Python/importlib.h b/Python/importlib.h index 88b89edb779b33dda3c6b8f3af878d66bde2fd99..0e2c734d9d7d0a6f9447bb042bb3d4da2d390878 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 21 02:36:57 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 21 Apr 2012 02:36:57 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_List_limitations_of?= =?utf8?q?_this_PEP?= Message-ID: http://hg.python.org/peps/rev/a96b9319dc84 changeset: 4290:a96b9319dc84 user: Victor Stinner date: Sat Apr 21 02:36:52 2012 +0200 summary: PEP 418: List limitations of this PEP files: pep-0418.txt | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -74,6 +74,27 @@ instead, depending on your requirements. ``time.clock()`` is marked as deprecated but is not planned for removal. +Limitations: + +* The behaviour of clocks after a system suspend is not defined in the + documentation of new functions. The behaviour depends on the + operating system: see the `Monotonic Clocks`_ section below. Some + recent operating systems provide two clocks, one including time + elapsed during system suspsend, one not including this time. Most + operating systems only provide one kind of clock. +* time.monotonic() and time.perf_counter() may or may not be adjusted. + For example, ``CLOCK_MONOTONIC`` is slewed on Linux, whereas + ``GetTickCount()`` is not adjusted on Windows. + ``time.get_clock_info('monotonic')['is_adjusted']`` can be used to check + if the monotonic clock is adjusted or not. +* No time.thread_time() function is proposed by this PEP because it is + not needed by Python standard library nor a common asked feature. + Such function would only be available on Windows and Linux. On + Linux, it is possible use use + ``time.clock_gettime(CLOCK_THREAD_CPUTIME_ID)``. On Windows, ctypes or + another module can be used to call the ``GetThreadTimes()`` + function. + Python functions ================ -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Sat Apr 21 05:33:38 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 21 Apr 2012 05:33:38 +0200 Subject: [Python-checkins] Daily reference leaks (c820aa9c0c00): sum=0 Message-ID: results for c820aa9c0c00 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogqFQpwY', '-x'] From python-checkins at python.org Sat Apr 21 16:30:57 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 21 Apr 2012 16:30:57 +0200 Subject: [Python-checkins] =?utf8?q?distutils2=3A_improved_the_test_covera?= =?utf8?q?ge_on_commands=2Ebdist?= Message-ID: http://hg.python.org/distutils2/rev/9d5ae0096406 changeset: 1313:9d5ae0096406 parent: 887:cb2aa326f4c3 user: Yannick Gingras date: Thu Dec 09 16:57:53 2010 -0500 summary: improved the test coverage on commands.bdist files: distutils2/tests/test_command_bdist.py | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-) diff --git a/distutils2/tests/test_command_bdist.py b/distutils2/tests/test_command_bdist.py --- a/distutils2/tests/test_command_bdist.py +++ b/distutils2/tests/test_command_bdist.py @@ -1,12 +1,13 @@ """Tests for distutils.command.bdist.""" +import os from distutils2 import util from distutils2.tests import run_unittest from distutils2.command.bdist import bdist, show_formats +from distutils2.errors import DistutilsPlatformError from distutils2.tests import unittest, support, captured_stdout - class BuildTestCase(support.TempdirManager, unittest.TestCase): @@ -61,6 +62,17 @@ cmd.ensure_finalized() self.assertTrue(self._get_platform_called) + def test_unsupported_platform(self): + try: + _os_name = os.name + os.name = "some-obscure-os" + + pkg_pth, dist = self.create_dist() + cmd = bdist(dist) + self.assertRaises(DistutilsPlatformError, cmd.ensure_finalized) + finally: + os.name = _os_name + def test_show_formats(self): __, stdout = captured_stdout(show_formats) -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Sat Apr 21 16:30:57 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 21 Apr 2012 16:30:57 +0200 Subject: [Python-checkins] =?utf8?q?distutils2_=28merge_default_-=3E_defau?= =?utf8?q?lt=29=3A_Merge_Yannick=E2=80=99s_test_into_main_repo?= Message-ID: http://hg.python.org/distutils2/rev/6e5312167b4a changeset: 1314:6e5312167b4a parent: 1312:e0d1ba9899d5 parent: 1313:9d5ae0096406 user: ?ric Araujo date: Sat Apr 21 10:30:23 2012 -0400 summary: Merge Yannick?s test into main repo files: distutils2/tests/test_command_bdist.py | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/distutils2/tests/test_command_bdist.py b/distutils2/tests/test_command_bdist.py --- a/distutils2/tests/test_command_bdist.py +++ b/distutils2/tests/test_command_bdist.py @@ -2,7 +2,9 @@ import os import sys from StringIO import StringIO +from distutils2.errors import PackagingPlatformError from distutils2.command.bdist import bdist, show_formats + from distutils2.tests import unittest, support @@ -43,6 +45,17 @@ self.assertTrue(subcmd.skip_build, '%s should take --skip-build from bdist' % name) + def test_unsupported_platform(self): + _os_name = os.name + try: + os.name = 'some-obscure-os' + + dist = self.create_dist()[1] + cmd = bdist(dist) + self.assertRaises(PackagingPlatformError, cmd.ensure_finalized) + finally: + os.name = _os_name + def test_show_formats(self): saved = sys.stdout sys.stdout = StringIO() -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Sat Apr 21 16:52:18 2012 From: python-checkins at python.org (michael.foord) Date: Sat, 21 Apr 2012 16:52:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Closes_issue_14636=2E_mock_?= =?utf8?q?objects_raise_exceptions_from_an_iterable_side=5Feffect?= Message-ID: http://hg.python.org/cpython/rev/c310233b1d64 changeset: 76446:c310233b1d64 user: Michael Foord date: Sat Apr 21 15:52:11 2012 +0100 summary: Closes issue 14636. mock objects raise exceptions from an iterable side_effect files: Doc/library/unittest.mock-examples.rst | 49 -------------- Doc/library/unittest.mock.rst | 14 ++++ Lib/unittest/mock.py | 10 ++- Lib/unittest/test/testmock/testmock.py | 10 ++ 4 files changed, 31 insertions(+), 52 deletions(-) diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -838,56 +838,6 @@ children of a `CopyingMock` will also have the type `CopyingMock`. -Multiple calls with different effects -------------------------------------- - -Handling code that needs to behave differently on subsequent calls during the -test can be tricky. For example you may have a function that needs to raise -an exception the first time it is called but returns a response on the second -call (testing retry behaviour). - -One approach is to use a :attr:`side_effect` function that replaces itself. The -first time it is called the `side_effect` sets a new `side_effect` that will -be used for the second call. It then raises an exception: - - >>> def side_effect(*args): - ... def second_call(*args): - ... return 'response' - ... mock.side_effect = second_call - ... raise Exception('boom') - ... - >>> mock = Mock(side_effect=side_effect) - >>> mock('first') - Traceback (most recent call last): - ... - Exception: boom - >>> mock('second') - 'response' - >>> mock.assert_called_with('second') - -Another perfectly valid way would be to pop return values from a list. If the -return value is an exception, raise it instead of returning it: - - >>> returns = [Exception('boom'), 'response'] - >>> def side_effect(*args): - ... result = returns.pop(0) - ... if isinstance(result, Exception): - ... raise result - ... return result - ... - >>> mock = Mock(side_effect=side_effect) - >>> mock('first') - Traceback (most recent call last): - ... - Exception: boom - >>> mock('second') - 'response' - >>> mock.assert_called_with('second') - -Which approach you prefer is a matter of taste. The first approach is actually -a line shorter but maybe the second approach is more readable. - - Nesting Patches --------------- diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -823,6 +823,20 @@ ... StopIteration +If any members of the iterable are exceptions they will be raised instead of +returned:: + + >>> iterable = (33, ValueError, 66) + >>> m = MagicMock(side_effect=iterable) + >>> m() + 33 + >>> m() + Traceback (most recent call last): + ... + ValueError + >>> m() + 66 + .. _deleting-attributes: diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -891,7 +891,10 @@ raise effect if not _callable(effect): - return next(effect) + result = next(effect) + if _is_exception(result): + raise result + return result ret_val = effect(*args, **kwargs) if ret_val is DEFAULT: @@ -931,8 +934,9 @@ arguments as the mock, and unless it returns `DEFAULT`, the return value of this function is used as the return value. - Alternatively `side_effect` can be an exception class or instance. In - this case the exception will be raised when the mock is called. + If `side_effect` is an iterable then each call to the mock will return + the next value from the iterable. If any of the members of the iterable + are exceptions they will be raised instead of returned. If `side_effect` is an iterable then each call to the mock will return the next value from the iterable. diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -868,6 +868,16 @@ self.assertRaises(StopIteration, mock) + def test_side_effect_iterator_exceptions(self): + for Klass in Mock, MagicMock: + iterable = (ValueError, 3, KeyError, 6) + m = Klass(side_effect=iterable) + self.assertRaises(ValueError, m) + self.assertEqual(m(), 3) + self.assertRaises(KeyError, m) + self.assertEqual(m(), 6) + + def test_side_effect_setting_iterator(self): mock = Mock() mock.side_effect = iter([1, 2, 3]) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 21 19:22:46 2012 From: python-checkins at python.org (michael.foord) Date: Sat, 21 Apr 2012 19:22:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Closes_issue_14634=2E_unitt?= =?utf8?q?est=2Emock=2Ecreate=5Fautospec_now_supports_keyword_only?= Message-ID: http://hg.python.org/cpython/rev/6f478a4aa137 changeset: 76447:6f478a4aa137 user: Michael Foord date: Sat Apr 21 18:22:28 2012 +0100 summary: Closes issue 14634. unittest.mock.create_autospec now supports keyword only arguments. files: Doc/library/inspect.rst | 13 ++++++-- Lib/unittest/mock.py | 11 +++++-- Lib/unittest/test/testmock/testhelpers.py | 15 ++++++++++- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -440,11 +440,16 @@ locals dictionary of the given frame. -.. function:: formatargspec(args[, varargs, varkw, defaults, formatarg, formatvarargs, formatvarkw, formatvalue]) +.. function:: formatargspec(args[, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations, formatarg, formatvarargs, formatvarkw, formatvalue, formatreturns, formatannotations]) - Format a pretty argument spec from the four values returned by - :func:`getargspec`. The format\* arguments are the corresponding optional - formatting functions that are called to turn names and values into strings. + Format a pretty argument spec from the values returned by + :func:`getargspec` or :func:`getfullargspec`. + + The first seven arguments are (``args``, ``varargs``, ``varkw``, + ``defaults``, ``kwonlyargs``, ``kwonlydefaults``, ``annotations``). The + other five arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The last argument + is an optional function to format the sequence of arguments. .. function:: formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue]) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -78,11 +78,15 @@ return try: - regargs, varargs, varkwargs, defaults = inspect.getargspec(func) + argspec = inspect.getfullargspec(func) except TypeError: # C function / method, possibly inherited object().__init__ return + # not using annotations + regargs, varargs, varkw, defaults, kwonly, kwonlydef, ann = argspec + + # instance methods and classmethods need to lose the self argument if getattr(func, '__self__', None) is not None: regargs = regargs[1:] @@ -90,8 +94,9 @@ # this condition and the above one are never both True - why? regargs = regargs[1:] - signature = inspect.formatargspec(regargs, varargs, varkwargs, defaults, - formatvalue=lambda value: "") + signature = inspect.formatargspec( + regargs, varargs, varkw, defaults, + kwonly, kwonlydef, ann, formatvalue=lambda value: "") return signature[1:-1], func diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -367,7 +367,7 @@ def test_create_autospec_unbound_methods(self): - # see issue 128 + # see mock issue 128 # this is expected to fail until the issue is fixed return class Foo(object): @@ -391,6 +391,19 @@ self.assertEqual(m.a, '3') + def test_create_autospec_keyword_only_arguments(self): + def foo(a, *, b=None): + pass + + m = create_autospec(foo) + m(1) + m.assert_called_with(1) + self.assertRaises(TypeError, m, 1, 2) + + m(2, b=3) + m.assert_called_with(2, b=3) + + def test_function_as_instance_attribute(self): obj = SomeClass() def f(a): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 21 19:33:06 2012 From: python-checkins at python.org (michael.foord) Date: Sat, 21 Apr 2012 19:33:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Remove_incorrect_comment?= Message-ID: http://hg.python.org/cpython/rev/d7c8914a9c4d changeset: 76448:d7c8914a9c4d user: Michael Foord date: Sat Apr 21 18:32:56 2012 +0100 summary: Remove incorrect comment files: Lib/unittest/mock.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -83,7 +83,6 @@ # C function / method, possibly inherited object().__init__ return - # not using annotations regargs, varargs, varkw, defaults, kwonly, kwonlydef, ann = argspec -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 21 21:18:07 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 21 Apr 2012 21:18:07 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Stephen_J=2E_Turnbu?= =?utf8?q?ll=27s_patch=3A_typos?= Message-ID: http://hg.python.org/peps/rev/df9de2807362 changeset: 4291:df9de2807362 user: Victor Stinner date: Sat Apr 21 21:16:37 2012 +0200 summary: PEP 418: Stephen J. Turnbull's patch: typos files: pep-0418.txt | 50 ++++++++++++++++++++-------------------- 1 files changed, 25 insertions(+), 25 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -49,7 +49,7 @@ differently, and it is useful to know exactly which function is used and some properties of the clock like its resolution and its precision. The new ``time.get_clock_info()`` function gives access to -all available information of each Python time function. +all available information about each Python time function. New functions: @@ -141,7 +141,7 @@ On Windows versions older than Vista, ``time.monotonic()`` detects ``GetTickCount()`` integer overflow (32 bits, roll-over after 49.7 -days): it increases a delta by 2\ :sup:`32` each time than an overflow +days): it increases a delta by 2\ :sup:`32` each time that an overflow is detected. The delta is stored in the process-local state and so the value of ``time.monotonic()`` may be different in two Python processes running for more than 49 days. On more recent versions of @@ -432,7 +432,7 @@ point. The name "time.try_monotonic()" was also proposed for an older -proposition of time.monotonic() which was falling back to the system +version of time.monotonic() which would fall back to the system time when no monotonic clock was available. Other names for time.perf_counter() @@ -461,11 +461,11 @@ Issues: -* It is hard to define correctly such function in the documentation: +* It is hard to define such a function correctly in the documentation: is it monotonic? Is it steady? Is it adjusted? -* Some user want to decide what to do when no monotonic clock is +* Some users want to decide what to do when no monotonic clock is available: use another clock, display an error, or do something - else? + else. Different APIs were proposed to define such function. @@ -499,7 +499,7 @@ Choosing the clock from a list of constraints --------------------------------------------- -The PEP as proposed offers a few new clocks, but their guarentees +The PEP as proposed offers a few new clocks, but their guarantees are deliberately loose in order to offer useful clocks on different platforms. This inherently embeds policy in the calls, and the caller must thus choose a policy. @@ -516,7 +516,7 @@ The primary interface is a function make simple choices easy: the caller can use ``time.get_clock(*flags)`` with some combination of flags. -This include at least: +This includes at least: * time.MONOTONIC: clock cannot go backward * time.STEADY: clock rate is steady @@ -536,7 +536,7 @@ The available clocks always at least include a wrapper for ``time.time()``, so a final call with no flags can always be used to obtain a working clock. -Example of flags of system clocks: +Examples of flags of system clocks: * QueryPerformanceCounter: MONOTONIC | HIGHRES * GetTickCount: MONOTONIC | STEADY @@ -606,7 +606,7 @@ :Clock: An instrument for measuring time. Different clocks have different - characteristics; for example, a clock with + characteristics; for example, a clock with may start to after a few minutes, while a less precise clock remained accurate for days. This PEP is primarily concerned with clocks which use a unit of seconds. @@ -723,7 +723,7 @@ * TSC (Time Stamp Counter): Historically, the TSC increased with every internal processor clock cycle, but now the rate is usually constant (even if the processor changes frequency) and usually equals the - maximum processor frequency. Multiple cores having different TSC + maximum processor frequency. Multiple cores have different TSC values. Hibernation of system will reset TSC value. The RDTSC instruction can be used to read this counter. CPU frequency scaling for power saving. @@ -734,10 +734,10 @@ IBM "Summit" series chipsets (ex: x440). This is available in IA32 and IA64 architectures. * PIT (programmable interrupt timer): Intel 8253/8254 chipsets with a - configurable frequency in range 18.2 Hz - 1.2 MHz. It is a 16-bit + configurable frequency in range 18.2 Hz - 1.2 MHz. It uses a 16-bit counter. * RTC (Real-time clock). Most RTCs use a crystal oscillator with a - frequency of 32,768 Hz + frequency of 32,768 Hz. Linux clocksource @@ -747,7 +747,7 @@ (1996), timer wheel (1997), HRT (2001) and hrtimers (2007). The latter is the result of the "high-res-timers" project started by George Anzinger in 2001, with contributions by Thomas Gleixner and -Douglas Niehaus. hrtimers implementation was merged into Linux +Douglas Niehaus. The hrtimers implementation was merged into Linux 2.6.21, released in 2007. hrtimers supports various clock sources. It sets a priority to each @@ -782,7 +782,7 @@ FreeBSD timecounter ------------------- -kern.timecounter.choice list available hardware clocks with their +kern.timecounter.choice lists available hardware clocks with their priority. The sysctl program can be used to change the timecounter. Example:: @@ -819,7 +819,7 @@ Performance ----------- -Reading an hardware clock has a cost. The following table compares +Reading a hardware clock has a cost. The following table compares the performance of different hardware clocks on Linux 3.3 with Intel Core i7-2600 at 3.40GHz (8 cores). The `bench_time.c `_ program @@ -864,7 +864,7 @@ ======================== ====== ========= ======= ======= Each function was called 100,000 times and CLOCK_MONOTONIC was used to -get the time before and after. The benchmark was run 5 times to keep +get the time before and after. The benchmark was run 5 times, keeping the minimum time. @@ -881,14 +881,14 @@ * "stepping": jump by a large amount in a single discrete step (which is done with ``settimeofday()``) -By default, the time is slewed if the offset is less than 128 ms, or +By default, the time is slewed if the offset is less than 128 ms, but stepped otherwise. Slewing is generally desirable (i.e. we should use CLOCK_MONOTONIC, not CLOCK_MONOTONIC_RAW) if one wishes to measure "real" time (and not a time-like object like CPU cycles). This is because the clock on the other end of the NTP connection from you is probably better at keeping -time: hopefully that thirty five thousand dollars of Cesium +time: hopefully that thirty-five thousand dollars of Cesium timekeeping goodness is doing something better than your PC's $3 quartz crystal, after all. @@ -1223,7 +1223,7 @@ Alexander Shishkin proposed an API for Linux to be notified when the system clock is changed: `timerfd: add TFD_NOTIFY_CLOCK_SET to watch for clock changes `_ (4th version of the API, March 2011). The -API is not accepted yet, CLOCK_BOOTTIME provides a similar feature. +API is not accepted yet, but CLOCK_BOOTTIME provides a similar feature. Process Time @@ -1291,7 +1291,7 @@ program. * getrusage(RUSAGE_SELF) returns a structure of resource usage of the currenet - process. ru_utime is use CPU time and ru_stime is the system CPU time. + process. ru_utime is user CPU time and ru_stime is the system CPU time. * times(): structure of process times. The precision is 1 / ticks_per_seconds, where ticks_per_seconds is sysconf(_SC_CLK_TCK) or the HZ constant. @@ -1466,11 +1466,11 @@ System Standby ============== -The ACPI power state "S3" is as system standby mode, also called +The ACPI power state "S3" is a system standby mode, also called "Suspend to RAM". RAM remains powered. -On Windows, the ``WM_POWERBROADCAST`` message is send to Windows -application to notify them of power-management events (ex: ower status +On Windows, the ``WM_POWERBROADCAST`` message is sent to Windows +applications to notify them of power-management events (ex: owner status has changed). For Mac OS X, read `Registering and unregistering for sleep and wake @@ -1484,7 +1484,7 @@ .. [#pseudo] "_time" is an hypothetical module only used for the example. The time module is implemented in C and so there is no need for - such module. + such a module. Links -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 21 21:18:08 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 21 Apr 2012 21:18:08 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Stephen_J=2E_Turnbu?= =?utf8?q?ll=27s_patch_2=3A_english?= Message-ID: http://hg.python.org/peps/rev/36943ff6a058 changeset: 4292:36943ff6a058 user: Victor Stinner date: Sat Apr 21 21:18:13 2012 +0200 summary: PEP 418: Stephen J. Turnbull's patch 2: english files: pep-0418.txt | 22 ++++++++++++---------- 1 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -22,8 +22,8 @@ ========= If a program uses the system time to schedule events or to implement -a timeout, it will not run events at the right moment or stop the -timeout too early or too late when the system time is set manually or +a timeout, it may fail to run events at the right moment or stop the +timeout too early or too late when the system time is changed manually or adjusted automatically by NTP. A monotonic clock should be used instead to not be affected by system time updates: ``time.monotonic()``. @@ -36,13 +36,14 @@ used instead to always get the most precise performance counter with a portable behaviour (ex: include time spend during sleep). -To measure CPU time, Python does not provide directly a portable -function. ``time.clock()`` can be used on Unix, but it has a bad +Until now, Python did not provide directly a portable +function to measure CPU time. ``time.clock()`` can be used on Unix, +but it has bad precision. ``resource.getrusage()`` or ``os.times()`` can also be used on Unix, but they require to compute the sum of time spent in kernel space and user space. The new ``time.process_time()`` function acts as a portable counter that always measures CPU time -(doesn't include time elapsed during sleep) and has the best available +(excluding time elapsed during sleep) and has the best available precision. Each operating system implements clocks and performance counters @@ -141,8 +142,9 @@ On Windows versions older than Vista, ``time.monotonic()`` detects ``GetTickCount()`` integer overflow (32 bits, roll-over after 49.7 -days): it increases a delta by 2\ :sup:`32` each time that an overflow -is detected. The delta is stored in the process-local state and so +days). It increases an internal epoch (reference time by) 2\ +:sup:`32` each time that an overflow is detected. The epoch is stored +in the process-local state and so the value of ``time.monotonic()`` may be different in two Python processes running for more than 49 days. On more recent versions of Windows and on other operating systems, ``time.monotonic()`` is @@ -563,7 +565,7 @@ Working around operating system bugs? ------------------------------------- -Should Python ensure manually that a monotonic clock is truly +Should Python ensure that a monotonic clock is truly monotonic by computing the maximum with the clock value and the previous value? @@ -578,7 +580,7 @@ `KB274323`_ contains a code example to workaround the bug (use GetTickCount() to detect QueryPerformanceCounter() leap). -Issues of a hacked monotonic function: +Issues with "correcting" non-monotonicities: * if the clock is accidentally set forward by an hour and then back again, you wouldn't have a useful clock for an hour @@ -946,7 +948,7 @@ ^^^^^^^^^^^^^^^^^^ Mac OS X provides a monotonic clock: mach_absolute_time(). It is -based on absolute elapsed time delta since system boot. It is not +based on absolute elapsed time since system boot. It is not adjusted and cannot be set. mach_timebase_info() gives a fraction to convert the clock value to a -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 21 21:24:53 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 21 Apr 2012 21:24:53 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Stephen_J=2E_Turnbu?= =?utf8?q?ll=27s_patch_3=3A_complete_the_Glossary?= Message-ID: http://hg.python.org/peps/rev/9e8299a885a5 changeset: 4293:9e8299a885a5 user: Victor Stinner date: Sat Apr 21 21:25:00 2012 +0200 summary: PEP 418: Stephen J. Turnbull's patch 3: complete the Glossary files: pep-0418.txt | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -595,6 +595,10 @@ The amount of deviation of measurements by a given instrument from true values. See also `Accuracy and precision `_. + Inaccuracy in clocks may be caused by lack of precision, drift, or an + incorrect initial setting of the clock (e.g., timing of threads is + inherently inaccurate because perfect synchronization in resetting + counters is quite difficult). :Adjusted: Resetting a clock to the correct time. This may be done either @@ -636,7 +640,9 @@ :Drift: The accumulated error against "true" time, as defined externally to - the system. + the system. Drift may be due to imprecision, or to a difference + between the average rate at which clock time advances and that of + real time. :Epoch: The reference point of a clock. For clocks providing , @@ -662,7 +668,9 @@ :Precision: The amount of deviation among measurements of the same physical - value by a single instrument. + value by a single instrument. Imprecision in clocks may be caused by + a fluctuation of the rate at which clock time advances relative to + real time, including clock adjustment by slewing. :Process Time: Time elapsed since the process began. It is typically measured in -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 21 22:09:58 2012 From: python-checkins at python.org (martin.v.loewis) Date: Sat, 21 Apr 2012 22:09:58 +0200 (CEST) Subject: [Python-checkins] r88950 - tracker/roundup-src/roundup/backends/rdbms_common.py Message-ID: <3VZlQt1sG4zMQW@mail.python.org> Author: martin.v.loewis Date: Sat Apr 21 22:09:58 2012 New Revision: 88950 Log: Disable xapian. Modified: tracker/roundup-src/roundup/backends/rdbms_common.py Modified: tracker/roundup-src/roundup/backends/rdbms_common.py ============================================================================== --- tracker/roundup-src/roundup/backends/rdbms_common.py (original) +++ tracker/roundup-src/roundup/backends/rdbms_common.py Sat Apr 21 22:09:58 2012 @@ -65,10 +65,13 @@ # support from roundup.backends.blobfiles import FileStorage -try: - from roundup.backends.indexer_xapian import Indexer -except ImportError: - from roundup.backends.indexer_rdbms import Indexer +# mvl 20120421: disable xapian usage because of various problems +#try: +# from roundup.backends.indexer_xapian import Indexer +#except ImportError: +# from roundup.backends.indexer_rdbms import Indexer +from roundup.backends.indexer_rdbms import Indexer + from roundup.backends.sessions_rdbms import Sessions, OneTimeKeys from roundup.date import Range From python-checkins at python.org Sun Apr 22 00:53:22 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 00:53:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Make_path_manipulation_more?= =?utf8?q?_robust_for_platforms_with_alternative_path?= Message-ID: http://hg.python.org/cpython/rev/163360370ad2 changeset: 76449:163360370ad2 parent: 76445:c820aa9c0c00 user: Brett Cannon date: Fri Apr 20 21:19:53 2012 -0400 summary: Make path manipulation more robust for platforms with alternative path separators. files: Lib/importlib/_bootstrap.py | 43 +++++++++++++++-------- Python/importlib.h | Bin 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -7,11 +7,8 @@ """ -# Injected modules are '_warnings', '_imp', 'sys', 'marshal', '_io', -# and '_os' (a.k.a. 'posix', 'nt' or 'os2'). -# Injected attribute is path_sep. -# Most injection is handled by _setup(). -# +# See importlib._setup() for what is injected into the global namespace. + # When editing this code be aware that code executed at import time CANNOT # reference any injected objects! This includes not only global code but also # anything specified at the class level. @@ -64,12 +61,23 @@ return x +def _path_join(*args): + """Replacement for os.path.join().""" + sep = path_sep if args[0][-1:] not in path_separators else args[0][-1] + return sep.join(x[:-len(path_sep)] if x.endswith(path_sep) else x + for x in args if x) -# XXX Could also expose Modules/getpath.c:joinpath() -def _path_join(*args): - """Replacement for os.path.join.""" - return path_sep.join(x[:-len(path_sep)] if x.endswith(path_sep) else x - for x in args if x) + +def _path_split(path): + """Replacement for os.path.split().""" + for x in reversed(path): + if x in path_separators: + sep = x + break + else: + sep = path_sep + front, _, tail = path.rpartition(sep) + return front, tail def _path_exists(path): @@ -388,7 +396,7 @@ def is_package(self, fullname): """Concrete implementation of InspectLoader.is_package by checking if the path returned by get_filename has a filename of '__init__.py'.""" - filename = self.get_filename(fullname).rpartition(path_sep)[2] + filename = _path_split(self.get_filename(fullname))[1] return filename.rsplit('.', 1)[0] == '__init__' def _bytes_from_bytecode(self, fullname, data, bytecode_path, source_stats): @@ -449,7 +457,7 @@ module.__cached__ = module.__file__ module.__package__ = name if self.is_package(name): - module.__path__ = [module.__file__.rsplit(path_sep, 1)[0]] + module.__path__ = [_path_split(module.__file__)[0]] else: module.__package__ = module.__package__.rpartition('.')[0] module.__loader__ = self @@ -604,11 +612,11 @@ def set_data(self, path, data): """Write bytes data to a file.""" - parent, _, filename = path.rpartition(path_sep) + parent, filename = _path_split(path) path_parts = [] # Figure out what directories are missing. while parent and not _path_isdir(parent): - parent, _, part = parent.rpartition(path_sep) + parent, part = _path_split(parent) path_parts.append(part) # Create needed directories. for part in reversed(path_parts): @@ -1142,7 +1150,9 @@ builtin_module = sys.modules[builtin_name] setattr(self_module, builtin_name, builtin_module) - for builtin_os, path_sep in [('posix', '/'), ('nt', '\\'), ('os2', '\\')]: + os_details = ('posix', ['/']), ('nt', ['\\', '/']), ('os2', ['\\', '/']) + for builtin_os, path_separators in os_details: + path_sep = path_separators[0] if builtin_os in sys.modules: os_module = sys.modules[builtin_os] break @@ -1151,7 +1161,7 @@ os_module = BuiltinImporter.load_module(builtin_os) # TODO: rip out os2 code after 3.3 is released as per PEP 11 if builtin_os == 'os2' and 'EMX GCC' in sys.version: - path_sep = '/' + path_sep = path_separators[1] break except ImportError: continue @@ -1159,6 +1169,7 @@ raise ImportError('importlib requires posix or nt') setattr(self_module, '_os', os_module) setattr(self_module, 'path_sep', path_sep) + setattr(self_module, 'path_separators', set(path_separators)) # Constants setattr(self_module, '_relax_case', _make_relax_case()) setattr(self_module, '_MAGIC_NUMBER', _imp_module.get_magic()) diff --git a/Python/importlib.h b/Python/importlib.h index 0e2c734d9d7d0a6f9447bb042bb3d4da2d390878..5798d962eb9a66279a8f7acf239604cd994d021a GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 00:53:23 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 00:53:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Re-implem?= =?utf8?q?ent_imp=2Ecache=5Ffrom=5Fsource=28=29_in_Lib/imp=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/b773a751c2e7 changeset: 76450:b773a751c2e7 user: Brett Cannon date: Fri Apr 20 21:44:46 2012 -0400 summary: Issue #13959: Re-implement imp.cache_from_source() in Lib/imp.py. files: Lib/imp.py | 6 +- Lib/importlib/_bootstrap.py | 32 +++++- Python/import.c | 111 ------------------------ Python/importlib.h | Bin 4 files changed, 30 insertions(+), 119 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -10,11 +10,10 @@ load_dynamic, get_frozen_object, is_frozen_package, init_builtin, init_frozen, is_builtin, is_frozen, _fix_co_filename) -# Can (probably) move to importlib -from _imp import (get_tag, get_suffixes, cache_from_source, - source_from_cache) # Could move out of _imp, but not worth the code from _imp import get_magic +# Can (probably) move to importlib +from _imp import (get_tag, get_suffixes, source_from_cache) # Should be re-implemented here (and mostly deprecated) from _imp import (find_module, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, @@ -22,6 +21,7 @@ PY_CODERESOURCE, IMP_HOOK) from importlib._bootstrap import _new_module as new_module +from importlib._bootstrap import _cache_from_source as cache_from_source from importlib import _bootstrap import os diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -178,6 +178,31 @@ # Finder/loader utility code ################################################## +PYCACHE = '__pycache__' + +DEBUG_BYTECODE_SUFFIX = '.pyc' +OPT_BYTECODE_SUFFIX = '.pyo' +BYTECODE_SUFFIX = DEBUG_BYTECODE_SUFFIX if __debug__ else OPT_BYTECODE_SUFFIX + +def _cache_from_source(path, debug_override=None): + """Given the path to a .py file, return the path to its .pyc/.pyo file. + + The .py file does not need to exist; this simply returns the path to the + .pyc/.pyo file calculated as if the .py file were imported. The extension + will be .pyc unless __debug__ is not defined, then it will be .pyo. + + If debug_override is not None, then it must be a boolean and is taken as + the value of __debug__ instead. + + """ + debug = __debug__ if debug_override is None else debug_override + suffix = DEBUG_BYTECODE_SUFFIX if debug else OPT_BYTECODE_SUFFIX + head, tail = _path_split(path) + base_filename, sep, _ = tail.partition('.') + filename = '{}{}{}{}'.format(base_filename, sep, _imp.get_tag(), suffix) + return _path_join(head, PYCACHE, filename) + + def verbose_message(message, *args): """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" if sys.flags.verbose: @@ -452,7 +477,7 @@ code_object = self.get_code(name) module.__file__ = self.get_filename(name) if not sourceless: - module.__cached__ = _imp.cache_from_source(module.__file__) + module.__cached__ = _cache_from_source(module.__file__) else: module.__cached__ = module.__file__ module.__package__ = name @@ -515,7 +540,7 @@ """ source_path = self.get_filename(fullname) - bytecode_path = _imp.cache_from_source(source_path) + bytecode_path = _cache_from_source(source_path) source_mtime = None if bytecode_path is not None: try: @@ -554,9 +579,6 @@ verbose_message('code object from {}', source_path) if (not sys.dont_write_bytecode and bytecode_path is not None and source_mtime is not None): - # If e.g. Jython ever implements imp.cache_from_source to have - # their own cached file format, this block of code will most likely - # throw an exception. data = bytearray(_MAGIC_NUMBER) data.extend(_w_long(source_mtime)) data.extend(_w_long(len(source_bytes))) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -783,7 +783,6 @@ static PyObject * get_sourcefile(PyObject *filename); static PyObject *make_source_pathname(PyObject *pathname); -static PyObject* make_compiled_pathname(PyObject *pathname, int debug); /* Execute a code object in a module and return the module object * WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is @@ -924,71 +923,6 @@ return found; } -/* Given a pathname for a Python source file, fill a buffer with the - pathname for the corresponding compiled file. Return the pathname - for the compiled file, or NULL if there's no space in the buffer. - Doesn't set an exception. - - foo.py -> __pycache__/foo..pyc - - pathstr is assumed to be "ready". -*/ - -static PyObject* -make_compiled_pathname(PyObject *pathstr, int debug) -{ - PyObject *result; - Py_ssize_t fname, ext, len, i, pos, taglen; - Py_ssize_t pycache_len = sizeof(CACHEDIR) - 1; - int kind; - void *data; - Py_UCS4 lastsep; - - /* Compute the output string size. */ - len = PyUnicode_GET_LENGTH(pathstr); - /* If there is no separator, this returns -1, so - fname will be 0. */ - fname = rightmost_sep_obj(pathstr, 0, len) + 1; - /* Windows: re-use the last separator character (/ or \\) when - appending the __pycache__ path. */ - if (fname > 0) - lastsep = PyUnicode_READ_CHAR(pathstr, fname -1); - else - lastsep = SEP; - ext = fname - 1; - for(i = fname; i < len; i++) - if (PyUnicode_READ_CHAR(pathstr, i) == '.') - ext = i + 1; - if (ext < fname) - /* No dot in filename; use entire filename */ - ext = len; - - /* result = pathstr[:fname] + "__pycache__" + SEP + - pathstr[fname:ext] + tag + ".py[co]" */ - taglen = strlen(pyc_tag); - result = PyUnicode_New(ext + pycache_len + 1 + taglen + 4, - PyUnicode_MAX_CHAR_VALUE(pathstr)); - if (!result) - return NULL; - kind = PyUnicode_KIND(result); - data = PyUnicode_DATA(result); - PyUnicode_CopyCharacters(result, 0, pathstr, 0, fname); - pos = fname; - for (i = 0; i < pycache_len; i++) - PyUnicode_WRITE(kind, data, pos++, CACHEDIR[i]); - PyUnicode_WRITE(kind, data, pos++, lastsep); - PyUnicode_CopyCharacters(result, pos, pathstr, - fname, ext - fname); - pos += ext - fname; - for (i = 0; pyc_tag[i]; i++) - PyUnicode_WRITE(kind, data, pos++, pyc_tag[i]); - PyUnicode_WRITE(kind, data, pos++, '.'); - PyUnicode_WRITE(kind, data, pos++, 'p'); - PyUnicode_WRITE(kind, data, pos++, 'y'); - PyUnicode_WRITE(kind, data, pos++, debug ? 'c' : 'o'); - return result; -} - /* Given a pathname to a Python byte compiled file, return the path to the source file, if the path matches the PEP 3147 format. This does not check @@ -2991,49 +2925,6 @@ \n\ Reload the module. The module must have been successfully imported before."); -static PyObject * -imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) -{ - static char *kwlist[] = {"path", "debug_override", NULL}; - - PyObject *pathname, *cpathname; - PyObject *debug_override = NULL; - int debug = !Py_OptimizeFlag; - - if (!PyArg_ParseTupleAndKeywords( - args, kws, "O&|O", kwlist, - PyUnicode_FSDecoder, &pathname, &debug_override)) - return NULL; - - if (debug_override != NULL && - (debug = PyObject_IsTrue(debug_override)) < 0) { - Py_DECREF(pathname); - return NULL; - } - - if (PyUnicode_READY(pathname) < 0) - return NULL; - - cpathname = make_compiled_pathname(pathname, debug); - Py_DECREF(pathname); - - if (cpathname == NULL) { - PyErr_Format(PyExc_SystemError, "path buffer too short"); - return NULL; - } - return cpathname; -} - -PyDoc_STRVAR(doc_cache_from_source, -"cache_from_source(path, [debug_override]) -> path\n\ -Given the path to a .py file, return the path to its .pyc/.pyo file.\n\ -\n\ -The .py file does not need to exist; this simply returns the path to the\n\ -.pyc/.pyo file calculated as if the .py file were imported. The extension\n\ -will be .pyc unless __debug__ is not defined, then it will be .pyo.\n\ -\n\ -If debug_override is not None, then it must be a boolean and is taken as\n\ -the value of __debug__ instead."); static PyObject * imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws) @@ -3116,8 +3007,6 @@ {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, {"reload", imp_reload, METH_O, doc_reload}, - {"cache_from_source", (PyCFunction)imp_cache_from_source, - METH_VARARGS | METH_KEYWORDS, doc_cache_from_source}, {"source_from_cache", (PyCFunction)imp_source_from_cache, METH_VARARGS | METH_KEYWORDS, doc_source_from_cache}, /* The rest are obsolete */ diff --git a/Python/importlib.h b/Python/importlib.h index 5798d962eb9a66279a8f7acf239604cd994d021a..754949303d9d603c73365947828a3e2657686063 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 00:53:24 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 00:53:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Re-implem?= =?utf8?q?ent_imp=2Esource=5Ffrom=5Fcache=28=29_in_Lib/imp=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/ea46ebba8a0f changeset: 76451:ea46ebba8a0f user: Brett Cannon date: Sat Apr 21 18:52:52 2012 -0400 summary: Issue #13959: Re-implement imp.source_from_cache() in Lib/imp.py. files: Lib/imp.py | 26 ++++++++++++++++++- Lib/importlib/_bootstrap.py | 6 +++- Python/import.c | 33 ------------------------ Python/importlib.h | Bin 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -13,7 +13,7 @@ # Could move out of _imp, but not worth the code from _imp import get_magic # Can (probably) move to importlib -from _imp import (get_tag, get_suffixes, source_from_cache) +from _imp import (get_tag, get_suffixes) # Should be re-implemented here (and mostly deprecated) from _imp import (find_module, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, @@ -27,6 +27,26 @@ import os +def source_from_cache(path): + """Given the path to a .pyc./.pyo file, return the path to its .py file. + + The .pyc/.pyo file does not need to exist; this simply returns the path to + the .py file calculated to correspond to the .pyc/.pyo file. If path does + not conform to PEP 3147 format, ValueError will be raised. + + """ + head, pycache_filename = os.path.split(path) + head, pycache = os.path.split(head) + if pycache != _bootstrap.PYCACHE: + raise ValueError('{} not bottom-level directory in ' + '{!r}'.format(_bootstrap.PYCACHE, path)) + if pycache_filename.count('.') != 2: + raise ValueError('expected only 2 dots in ' + '{!r}'.format(pycache_filename)) + base_filename = pycache_filename.partition('.')[0] + return os.path.join(head, base_filename + _bootstrap.SOURCE_SUFFIXES[0]) + + class _HackedGetData: """Compatibiilty support for 'file' arguments of various load_*() @@ -55,6 +75,7 @@ """Compatibility support for implementing load_source().""" +# XXX deprecate after better API exposed in importlib def load_source(name, pathname, file=None): return _LoadSourceCompatibility(name, pathname, file).load_module(name) @@ -65,10 +86,12 @@ """Compatibility support for implementing load_compiled().""" +# XXX deprecate def load_compiled(name, pathname, file=None): return _LoadCompiledCompatibility(name, pathname, file).load_module(name) +# XXX deprecate def load_package(name, path): if os.path.isdir(path): extensions = _bootstrap._suffix_list(PY_SOURCE) @@ -82,6 +105,7 @@ return _bootstrap._SourceFileLoader(name, path).load_module(name) +# XXX deprecate def load_module(name, file, filename, details): """Load a module, given information returned by find_module(). diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -180,6 +180,8 @@ PYCACHE = '__pycache__' +SOURCE_SUFFIXES = ['.py'] # _setup() adds .pyw as needed. + DEBUG_BYTECODE_SUFFIX = '.pyc' OPT_BYTECODE_SUFFIX = '.pyo' BYTECODE_SUFFIX = DEBUG_BYTECODE_SUFFIX if __debug__ else OPT_BYTECODE_SUFFIX @@ -199,7 +201,7 @@ suffix = DEBUG_BYTECODE_SUFFIX if debug else OPT_BYTECODE_SUFFIX head, tail = _path_split(path) base_filename, sep, _ = tail.partition('.') - filename = '{}{}{}{}'.format(base_filename, sep, _imp.get_tag(), suffix) + filename = ''.join([base_filename, sep, _imp.get_tag(), suffix]) return _path_join(head, PYCACHE, filename) @@ -1195,6 +1197,8 @@ # Constants setattr(self_module, '_relax_case', _make_relax_case()) setattr(self_module, '_MAGIC_NUMBER', _imp_module.get_magic()) + if builtin_os == 'nt': + SOURCE_SUFFIXES.append('.pyw') def _install(sys_module, _imp_module): diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2926,36 +2926,6 @@ Reload the module. The module must have been successfully imported before."); -static PyObject * -imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws) -{ - static char *kwlist[] = {"path", NULL}; - PyObject *pathname, *source; - - if (!PyArg_ParseTupleAndKeywords( - args, kws, "O&", kwlist, - PyUnicode_FSDecoder, &pathname)) - return NULL; - - source = make_source_pathname(pathname); - if (source == NULL) { - PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %R", - pathname); - Py_DECREF(pathname); - return NULL; - } - Py_DECREF(pathname); - return source; -} - -PyDoc_STRVAR(doc_source_from_cache, -"source_from_cache(path) -> path\n\ -Given the path to a .pyc./.pyo file, return the path to its .py file.\n\ -\n\ -The .pyc/.pyo file does not need to exist; this simply returns the path to\n\ -the .py file calculated to correspond to the .pyc/.pyo file. If path\n\ -does not conform to PEP 3147 format, ValueError will be raised."); - /* Doc strings */ PyDoc_STRVAR(doc_imp, @@ -3007,9 +2977,6 @@ {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, {"reload", imp_reload, METH_O, doc_reload}, - {"source_from_cache", (PyCFunction)imp_source_from_cache, - METH_VARARGS | METH_KEYWORDS, doc_source_from_cache}, - /* The rest are obsolete */ {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, {"is_frozen_package", imp_is_frozen_package, METH_VARARGS}, {"init_builtin", imp_init_builtin, METH_VARARGS}, diff --git a/Python/importlib.h b/Python/importlib.h index 754949303d9d603c73365947828a3e2657686063..c369e3c3d370995a3f8e808c1705ffe9037db96c GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 00:53:25 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 00:53:25 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/1296da8b216f changeset: 76452:1296da8b216f parent: 76451:ea46ebba8a0f parent: 76448:d7c8914a9c4d user: Brett Cannon date: Sat Apr 21 18:53:14 2012 -0400 summary: merge files: Doc/library/inspect.rst | 13 ++- Doc/library/unittest.mock-examples.rst | 49 ----------- Doc/library/unittest.mock.rst | 14 +++ Lib/unittest/mock.py | 20 +++- Lib/unittest/test/testmock/testhelpers.py | 15 +++- Lib/unittest/test/testmock/testmock.py | 10 ++ 6 files changed, 61 insertions(+), 60 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -440,11 +440,16 @@ locals dictionary of the given frame. -.. function:: formatargspec(args[, varargs, varkw, defaults, formatarg, formatvarargs, formatvarkw, formatvalue]) +.. function:: formatargspec(args[, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations, formatarg, formatvarargs, formatvarkw, formatvalue, formatreturns, formatannotations]) - Format a pretty argument spec from the four values returned by - :func:`getargspec`. The format\* arguments are the corresponding optional - formatting functions that are called to turn names and values into strings. + Format a pretty argument spec from the values returned by + :func:`getargspec` or :func:`getfullargspec`. + + The first seven arguments are (``args``, ``varargs``, ``varkw``, + ``defaults``, ``kwonlyargs``, ``kwonlydefaults``, ``annotations``). The + other five arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The last argument + is an optional function to format the sequence of arguments. .. function:: formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue]) diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -838,56 +838,6 @@ children of a `CopyingMock` will also have the type `CopyingMock`. -Multiple calls with different effects -------------------------------------- - -Handling code that needs to behave differently on subsequent calls during the -test can be tricky. For example you may have a function that needs to raise -an exception the first time it is called but returns a response on the second -call (testing retry behaviour). - -One approach is to use a :attr:`side_effect` function that replaces itself. The -first time it is called the `side_effect` sets a new `side_effect` that will -be used for the second call. It then raises an exception: - - >>> def side_effect(*args): - ... def second_call(*args): - ... return 'response' - ... mock.side_effect = second_call - ... raise Exception('boom') - ... - >>> mock = Mock(side_effect=side_effect) - >>> mock('first') - Traceback (most recent call last): - ... - Exception: boom - >>> mock('second') - 'response' - >>> mock.assert_called_with('second') - -Another perfectly valid way would be to pop return values from a list. If the -return value is an exception, raise it instead of returning it: - - >>> returns = [Exception('boom'), 'response'] - >>> def side_effect(*args): - ... result = returns.pop(0) - ... if isinstance(result, Exception): - ... raise result - ... return result - ... - >>> mock = Mock(side_effect=side_effect) - >>> mock('first') - Traceback (most recent call last): - ... - Exception: boom - >>> mock('second') - 'response' - >>> mock.assert_called_with('second') - -Which approach you prefer is a matter of taste. The first approach is actually -a line shorter but maybe the second approach is more readable. - - Nesting Patches --------------- diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -823,6 +823,20 @@ ... StopIteration +If any members of the iterable are exceptions they will be raised instead of +returned:: + + >>> iterable = (33, ValueError, 66) + >>> m = MagicMock(side_effect=iterable) + >>> m() + 33 + >>> m() + Traceback (most recent call last): + ... + ValueError + >>> m() + 66 + .. _deleting-attributes: diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -78,11 +78,14 @@ return try: - regargs, varargs, varkwargs, defaults = inspect.getargspec(func) + argspec = inspect.getfullargspec(func) except TypeError: # C function / method, possibly inherited object().__init__ return + regargs, varargs, varkw, defaults, kwonly, kwonlydef, ann = argspec + + # instance methods and classmethods need to lose the self argument if getattr(func, '__self__', None) is not None: regargs = regargs[1:] @@ -90,8 +93,9 @@ # this condition and the above one are never both True - why? regargs = regargs[1:] - signature = inspect.formatargspec(regargs, varargs, varkwargs, defaults, - formatvalue=lambda value: "") + signature = inspect.formatargspec( + regargs, varargs, varkw, defaults, + kwonly, kwonlydef, ann, formatvalue=lambda value: "") return signature[1:-1], func @@ -891,7 +895,10 @@ raise effect if not _callable(effect): - return next(effect) + result = next(effect) + if _is_exception(result): + raise result + return result ret_val = effect(*args, **kwargs) if ret_val is DEFAULT: @@ -931,8 +938,9 @@ arguments as the mock, and unless it returns `DEFAULT`, the return value of this function is used as the return value. - Alternatively `side_effect` can be an exception class or instance. In - this case the exception will be raised when the mock is called. + If `side_effect` is an iterable then each call to the mock will return + the next value from the iterable. If any of the members of the iterable + are exceptions they will be raised instead of returned. If `side_effect` is an iterable then each call to the mock will return the next value from the iterable. diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -367,7 +367,7 @@ def test_create_autospec_unbound_methods(self): - # see issue 128 + # see mock issue 128 # this is expected to fail until the issue is fixed return class Foo(object): @@ -391,6 +391,19 @@ self.assertEqual(m.a, '3') + def test_create_autospec_keyword_only_arguments(self): + def foo(a, *, b=None): + pass + + m = create_autospec(foo) + m(1) + m.assert_called_with(1) + self.assertRaises(TypeError, m, 1, 2) + + m(2, b=3) + m.assert_called_with(2, b=3) + + def test_function_as_instance_attribute(self): obj = SomeClass() def f(a): diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -868,6 +868,16 @@ self.assertRaises(StopIteration, mock) + def test_side_effect_iterator_exceptions(self): + for Klass in Mock, MagicMock: + iterable = (ValueError, 3, KeyError, 6) + m = Klass(side_effect=iterable) + self.assertRaises(ValueError, m) + self.assertEqual(m(), 3) + self.assertRaises(KeyError, m) + self.assertEqual(m(), 6) + + def test_side_effect_setting_iterator(self): mock = Mock() mock.side_effect = iter([1, 2, 3]) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 00:56:02 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 00:56:02 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Don=27t_worry_about_moving_?= =?utf8?b?aW1wLmdldF90YWcoKSBvdmVyIHRvIExpYi9pbXAucHku?= Message-ID: http://hg.python.org/cpython/rev/024660a2faaa changeset: 76453:024660a2faaa user: Brett Cannon date: Sat Apr 21 18:55:51 2012 -0400 summary: Don't worry about moving imp.get_tag() over to Lib/imp.py. files: Lib/imp.py | 4 ++-- Lib/importlib/_bootstrap.py | 4 +++- Python/importlib.h | Bin 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -11,9 +11,9 @@ init_builtin, init_frozen, is_builtin, is_frozen, _fix_co_filename) # Could move out of _imp, but not worth the code -from _imp import get_magic +from _imp import get_magic, get_tag # Can (probably) move to importlib -from _imp import (get_tag, get_suffixes) +from _imp import get_suffixes # Should be re-implemented here (and mostly deprecated) from _imp import (find_module, NullImporter, SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -201,7 +201,7 @@ suffix = DEBUG_BYTECODE_SUFFIX if debug else OPT_BYTECODE_SUFFIX head, tail = _path_split(path) base_filename, sep, _ = tail.partition('.') - filename = ''.join([base_filename, sep, _imp.get_tag(), suffix]) + filename = ''.join([base_filename, sep, _TAG, suffix]) return _path_join(head, PYCACHE, filename) @@ -1148,6 +1148,7 @@ _MAGIC_NUMBER = None # Set in _setup() +_TAG = None # Set in _setup() def _setup(sys_module, _imp_module): @@ -1197,6 +1198,7 @@ # Constants setattr(self_module, '_relax_case', _make_relax_case()) setattr(self_module, '_MAGIC_NUMBER', _imp_module.get_magic()) + setattr(self_module, '_TAG', _imp.get_tag()) if builtin_os == 'nt': SOURCE_SUFFIXES.append('.pyw') diff --git a/Python/importlib.h b/Python/importlib.h index c369e3c3d370995a3f8e808c1705ffe9037db96c..c48b5507699c679b7353d7e96ca9f4965da97c5b GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 01:12:05 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 01:12:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314637=3A_Fix_the_U?= =?utf8?q?NC_import_test_under_Windows_to_actually_use?= Message-ID: http://hg.python.org/cpython/rev/0356103cde28 changeset: 76454:0356103cde28 user: Brett Cannon date: Sat Apr 21 19:11:58 2012 -0400 summary: Issue #14637: Fix the UNC import test under Windows to actually use the UNC path. Also clean up sys.path and invalidate finder caches. Thanks to Vinay Sajip for spotting the use of the wrong path. files: Lib/test/test_import.py | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -459,6 +459,7 @@ def test_UNC_path(self): with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f: f.write("testdata = 'test_trailing_slash'") + importlib.invalidate_caches() # Create the UNC path, like \\myhost\c$\foo\bar. path = os.path.abspath(self.path) import socket @@ -466,10 +467,13 @@ drive = path[0] unc = "\\\\%s\\%s$"%(hn, drive) unc += path[2:] - sys.path.append(path) - mod = __import__("test_trailing_slash") - self.assertEqual(mod.testdata, 'test_trailing_slash') - unload("test_trailing_slash") + sys.path.append(unc) + try: + mod = __import__("test_trailing_slash") + self.assertEqual(mod.testdata, 'test_trailing_slash') + unload("test_trailing_slash") + finally: + sys.path.remove(unc) class RelativeImportTests(unittest.TestCase): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 03:15:33 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 03:15:33 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Re-implem?= =?utf8?q?ent_imp=2Efind=5Fmodule=28=29_in_Lib/imp=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/085cf1480cfe changeset: 76455:085cf1480cfe user: Brett Cannon date: Sat Apr 21 21:09:46 2012 -0400 summary: Issue #13959: Re-implement imp.find_module() in Lib/imp.py. Thanks to Eric Snow for taking an initial stab at the implementation. files: Lib/imp.py | 72 +++- Python/import.c | 751 ------------------------------------ 2 files changed, 68 insertions(+), 755 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -15,16 +15,29 @@ # Can (probably) move to importlib from _imp import get_suffixes # Should be re-implemented here (and mostly deprecated) -from _imp import (find_module, NullImporter, - SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, - PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, - PY_CODERESOURCE, IMP_HOOK) +from _imp import NullImporter from importlib._bootstrap import _new_module as new_module from importlib._bootstrap import _cache_from_source as cache_from_source from importlib import _bootstrap import os +import sys +import tokenize + + +# XXX "deprecate" once find_module(), load_module(), and get_suffixes() are +# deprecated. +SEARCH_ERROR = 0 +PY_SOURCE = 1 +PY_COMPILED = 2 +C_EXTENSION = 3 +PY_RESOURCE = 4 +PKG_DIRECTORY = 5 +C_BUILTIN = 6 +PY_FROZEN = 7 +PY_CODERESOURCE = 8 +IMP_HOOK = 9 def source_from_cache(path): @@ -131,3 +144,54 @@ else: msg = "Don't know how to import {} (type code {}".format(name, type_) raise ImportError(msg, name=name) + + +def find_module(name, path=None): + """Search for a module. + + If path is omitted or None, search for a built-in, frozen or special + module and continue search in sys.path. The module name cannot + contain '.'; to search for a submodule of a package, pass the + submodule name and the package's __path__. + + """ + if not isinstance(name, str): + raise TypeError("'name' must be a str, not {}".format(type(name))) + elif not isinstance(path, (type(None), list)): + # Backwards-compatibility + raise RuntimeError("'list' must be None or a list, " + "not {}".format(type(name))) + + if path is None: + if is_builtin(name): + return None, None, ('', '', C_BUILTIN) + elif is_frozen(name): + return None, None, ('', '', PY_FROZEN) + else: + path = sys.path + + for entry in path: + package_directory = os.path.join(entry, name) + for suffix in ['.py', _bootstrap.BYTECODE_SUFFIX]: + package_file_name = '__init__' + suffix + file_path = os.path.join(package_directory, package_file_name) + if os.path.isfile(file_path): + return None, package_directory, ('', '', PKG_DIRECTORY) + for suffix, mode, type_ in get_suffixes(): + file_name = name + suffix + file_path = os.path.join(entry, file_name) + if os.path.isfile(file_path): + break + else: + continue + break # Break out of outer loop when breaking out of inner loop. + else: + raise ImportError('No module name {!r}'.format(name), name=name) + + encoding = None + if mode == 'U': + with open(file_path, 'rb') as file: + encoding = tokenize.detect_encoding(file.readline)[0] + file = open(file_path, mode, encoding=encoding) + return file, file_path, (suffix, mode, type_) + diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1118,8 +1118,6 @@ } /* Forward */ -static struct filedescr *find_module(PyObject *, PyObject *, PyObject *, - PyObject **, FILE **, PyObject **); static struct _frozen * find_frozen(PyObject *); @@ -1220,678 +1218,12 @@ return importer; } -/* Search the path (default sys.path) for a module. Return the - corresponding filedescr struct, and (via return arguments) the - pathname and an open file. Return NULL if the module is not found. */ #ifdef MS_COREDLL extern FILE *_PyWin_FindRegisteredModule(PyObject *, struct filedescr **, PyObject **p_path); #endif -/* Forward */ -static int case_ok(PyObject *, Py_ssize_t, PyObject *); -static int find_init_module(PyObject *); -static struct filedescr importhookdescr = {"", "", IMP_HOOK}; - -/* Get the path of a module: get its importer and call importer.find_module() - hook, or check if the module if a package (if path/__init__.py exists). - - -1: error: a Python error occurred - 0: ignore: an error occurred because of invalid data, but the error is not - important enough to be reported. - 1: get path: module not found, but *buf contains its path - 2: found: *p_fd is the file descriptor (IMP_HOOK or PKG_DIRECTORY) - and *buf is the path */ - -static int -find_module_path(PyObject *fullname, PyObject *name, PyObject *path, - PyObject *path_hooks, PyObject *path_importer_cache, - PyObject **p_path, PyObject **p_loader, struct filedescr **p_fd) -{ - PyObject *path_unicode, *filename = NULL; - Py_ssize_t len, pos; - struct stat statbuf; - static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; - int err, result, addsep; - - if (PyUnicode_Check(path)) { - Py_INCREF(path); - path_unicode = path; - } - else if (PyBytes_Check(path)) { - path_unicode = PyUnicode_DecodeFSDefaultAndSize( - PyBytes_AS_STRING(path), PyBytes_GET_SIZE(path)); - if (path_unicode == NULL) - return -1; - } - else - return 0; - - if (PyUnicode_READY(path_unicode)) - return -1; - - len = PyUnicode_GET_LENGTH(path_unicode); - if (PyUnicode_FindChar(path_unicode, 0, 0, len, 1) != -1) { - result = 0; - goto out; /* path contains '\0' */ - } - - /* sys.path_hooks import hook */ - if (p_loader != NULL) { - _Py_IDENTIFIER(find_module); - PyObject *importer; - - importer = get_path_importer(path_importer_cache, - path_hooks, path); - if (importer == NULL) { - result = -1; - goto out; - } - /* Note: importer is a borrowed reference */ - if (importer != Py_None) { - PyObject *loader; - loader = _PyObject_CallMethodId(importer, - &PyId_find_module, "O", fullname); - if (loader == NULL) { - result = -1; /* error */ - goto out; - } - if (loader != Py_None) { - /* a loader was found */ - *p_loader = loader; - *p_fd = &importhookdescr; - result = 2; - goto out; - } - Py_DECREF(loader); - result = 0; - goto out; - } - } - /* no hook was found, use builtin import */ - - addsep = 0; - if (len > 0 && PyUnicode_READ_CHAR(path_unicode, len-1) != SEP -#ifdef ALTSEP - && PyUnicode_READ_CHAR(path_unicode, len-1) != ALTSEP -#endif - ) - addsep = 1; - filename = PyUnicode_New(len + PyUnicode_GET_LENGTH(name) + addsep, - Py_MAX(PyUnicode_MAX_CHAR_VALUE(path_unicode), - PyUnicode_MAX_CHAR_VALUE(name))); - if (filename == NULL) { - result = -1; - goto out; - } - PyUnicode_CopyCharacters(filename, 0, path_unicode, 0, len); - pos = len; - if (addsep) - PyUnicode_WRITE(PyUnicode_KIND(filename), - PyUnicode_DATA(filename), - pos++, SEP); - PyUnicode_CopyCharacters(filename, pos, name, 0, - PyUnicode_GET_LENGTH(name)); - - /* Check for package import (buf holds a directory name, - and there's an __init__ module in that directory */ -#ifdef HAVE_STAT - err = _Py_stat(filename, &statbuf); - if (err == -2) { - result = -1; - goto out; - } - if (err == 0 && /* it exists */ - S_ISDIR(statbuf.st_mode)) /* it's a directory */ - { - int match; - - match = case_ok(filename, 0, name); - if (match < 0) { - result = -1; - goto out; - } - if (match) { /* case matches */ - if (find_init_module(filename)) { /* and has __init__.py */ - *p_path = filename; - filename = NULL; - *p_fd = &fd_package; - result = 2; - goto out; - } - else { - int err; - err = PyErr_WarnFormat(PyExc_ImportWarning, 1, - "Not importing directory %R: missing __init__.py", - filename); - if (err) { - result = -1; - goto out; - } - } - } - } -#endif - *p_path = filename; - filename = NULL; - result = 1; - out: - Py_DECREF(path_unicode); - Py_XDECREF(filename); - return result; -} - -/* Find a module in search_path_list. For each path, try - find_module_path() or try each _PyImport_Filetab suffix. - - If the module is found, return a file descriptor, write the path in - *p_filename, write the pointer to the file object into *p_fp, and (if - p_loader is not NULL) the loader into *p_loader. - - Otherwise, raise an exception and return NULL. */ - -static struct filedescr* -find_module_path_list(PyObject *fullname, PyObject *name, - PyObject *search_path_list, PyObject *path_hooks, - PyObject *path_importer_cache, - PyObject **p_path, FILE **p_fp, PyObject **p_loader) -{ - Py_ssize_t i, npath; - struct filedescr *fdp = NULL; - char *filemode; - FILE *fp = NULL; - PyObject *prefix, *filename; - int match; - int err; - - npath = PyList_Size(search_path_list); - for (i = 0; i < npath; i++) { - PyObject *path; - int ok; - - path = PyList_GetItem(search_path_list, i); - if (path == NULL) - return NULL; - - prefix = NULL; - ok = find_module_path(fullname, name, path, - path_hooks, path_importer_cache, - &prefix, p_loader, &fdp); - if (ok < 0) - return NULL; - if (ok == 0) - continue; - if (ok == 2) { - *p_path = prefix; - return fdp; - } - - for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { - struct stat statbuf; - - filemode = fdp->mode; - if (filemode[0] == 'U') - filemode = "r" PY_STDIOTEXTMODE; - - filename = PyUnicode_FromFormat("%U%s", prefix, fdp->suffix); - if (filename == NULL) { - Py_DECREF(prefix); - return NULL; - } - - if (Py_VerboseFlag > 1) - PySys_FormatStderr("# trying %R\n", filename); - - err = _Py_stat(filename, &statbuf); - if (err == -2) { - Py_DECREF(prefix); - Py_DECREF(filename); - return NULL; - } - if (err != 0 || S_ISDIR(statbuf.st_mode)) { - /* it doesn't exist, or it's a directory */ - Py_DECREF(filename); - continue; - } - - fp = _Py_fopen(filename, filemode); - if (fp == NULL) { - Py_DECREF(filename); - if (PyErr_Occurred()) { - Py_DECREF(prefix); - return NULL; - } - continue; - } - match = case_ok(filename, -(Py_ssize_t)strlen(fdp->suffix), name); - if (match < 0) { - Py_DECREF(prefix); - Py_DECREF(filename); - return NULL; - } - if (match) { - Py_DECREF(prefix); - *p_path = filename; - *p_fp = fp; - return fdp; - } - Py_DECREF(filename); - - fclose(fp); - fp = NULL; - } - Py_DECREF(prefix); - } - PyErr_Format(PyExc_ImportError, - "No module named %R", name); - return NULL; -} - -/* Find a module: - - - try find_module() of each sys.meta_path hook - - try find_frozen() - - try is_builtin() - - try _PyWin_FindRegisteredModule() (Windows only) - - otherwise, call find_module_path_list() with search_path_list (if not - NULL) or sys.path - - fullname can be NULL, but only if p_loader is NULL. - - Return: - - - &fd_builtin (C_BUILTIN) if it is a builtin - - &fd_frozen (PY_FROZEN) if it is frozen - - &fd_package (PKG_DIRECTORY) and write the filename into *p_path - if it is a package - - &importhookdescr (IMP_HOOK) and write the loader into *p_loader if a - importer loader was found - - a file descriptor (PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE or - PY_CODERESOURCE: see _PyImport_Filetab), write the filename into - *p_path and the pointer to the open file into *p_fp - - NULL on error - - By default, *p_path, *p_fp and *p_loader (if set) are set to NULL. - Eg. *p_path is set to NULL for a builtin package. -*/ - -static struct filedescr * -find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, - PyObject **p_path, FILE **p_fp, PyObject **p_loader) -{ - Py_ssize_t i, npath; - static struct filedescr fd_frozen = {"", "", PY_FROZEN}; - static struct filedescr fd_builtin = {"", "", C_BUILTIN}; - PyObject *path_hooks, *path_importer_cache; - - *p_path = NULL; - *p_fp = NULL; - if (p_loader != NULL) - *p_loader = NULL; - - /* sys.meta_path import hook */ - if (p_loader != NULL) { - _Py_IDENTIFIER(find_module); - PyObject *meta_path; - - meta_path = PySys_GetObject("meta_path"); - if (meta_path == NULL || !PyList_Check(meta_path)) { - PyErr_SetString(PyExc_RuntimeError, - "sys.meta_path must be a list of " - "import hooks"); - return NULL; - } - Py_INCREF(meta_path); /* zap guard */ - npath = PyList_Size(meta_path); - for (i = 0; i < npath; i++) { - PyObject *loader; - PyObject *hook = PyList_GetItem(meta_path, i); - loader = _PyObject_CallMethodId(hook, &PyId_find_module, - "OO", fullname, - search_path_list != NULL ? - search_path_list : Py_None); - if (loader == NULL) { - Py_DECREF(meta_path); - return NULL; /* true error */ - } - if (loader != Py_None) { - /* a loader was found */ - *p_loader = loader; - Py_DECREF(meta_path); - return &importhookdescr; - } - Py_DECREF(loader); - } - Py_DECREF(meta_path); - } - - if (find_frozen(fullname) != NULL) - return &fd_frozen; - - if (search_path_list == NULL) { -#ifdef MS_COREDLL - FILE *fp; - struct filedescr *fdp; -#endif - if (is_builtin(name)) - return &fd_builtin; -#ifdef MS_COREDLL - fp = _PyWin_FindRegisteredModule(name, &fdp, p_path); - if (fp != NULL) { - *p_fp = fp; - return fdp; - } - else if (PyErr_Occurred()) - return NULL; -#endif - search_path_list = PySys_GetObject("path"); - } - - if (search_path_list == NULL || !PyList_Check(search_path_list)) { - PyErr_SetString(PyExc_RuntimeError, - "sys.path must be a list of directory names"); - return NULL; - } - - path_hooks = PySys_GetObject("path_hooks"); - if (path_hooks == NULL || !PyList_Check(path_hooks)) { - PyErr_SetString(PyExc_RuntimeError, - "sys.path_hooks must be a list of " - "import hooks"); - return NULL; - } - path_importer_cache = PySys_GetObject("path_importer_cache"); - if (path_importer_cache == NULL || - !PyDict_Check(path_importer_cache)) { - PyErr_SetString(PyExc_RuntimeError, - "sys.path_importer_cache must be a dict"); - return NULL; - } - - return find_module_path_list(fullname, name, - search_path_list, path_hooks, - path_importer_cache, - p_path, p_fp, p_loader); -} - -/* case_bytes(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name) - * The arguments here are tricky, best shown by example: - * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0 - * ^ ^ ^ ^ - * |--------------------- buf ---------------------| - * |------------------- len ------------------| - * |------ name -------| - * |----- namelen -----| - * buf is the full path, but len only counts up to (& exclusive of) the - * extension. name is the module name, also exclusive of extension. - * - * We've already done a successful stat() or fopen() on buf, so know that - * there's some match, possibly case-insensitive. - * - * case_bytes() is to return 1 if there's a case-sensitive match for - * name, else 0. case_bytes() is also to return 1 if envar PYTHONCASEOK - * exists. - * - * case_bytes() is used to implement case-sensitive import semantics even - * on platforms with case-insensitive filesystems. It's trivial to implement - * for case-sensitive filesystems. It's pretty much a cross-platform - * nightmare for systems with case-insensitive filesystems. - */ - -/* First we may need a pile of platform-specific header files; the sequence - * of #if's here should match the sequence in the body of case_bytes(). - */ -#if defined(MS_WINDOWS) -#include - -#elif defined(DJGPP) -#include - -#elif (defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) -#include -#include - -#elif defined(PYOS_OS2) -#define INCL_DOS -#define INCL_DOSERRORS -#define INCL_NOPMAPI -#include -#endif - -#if defined(DJGPP) \ - || ((defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) \ - && defined(HAVE_DIRENT_H)) \ - || defined(PYOS_OS2) -# define USE_CASE_OK_BYTES -#endif - - -#ifdef USE_CASE_OK_BYTES -static int -case_bytes(char *buf, Py_ssize_t len, Py_ssize_t namelen, const char *name) -{ -/* Pick a platform-specific implementation; the sequence of #if's here should - * match the sequence just above. - */ - -/* DJGPP */ -#if defined(DJGPP) - struct ffblk ffblk; - int done; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - done = findfirst(buf, &ffblk, FA_ARCH|FA_RDONLY|FA_HIDDEN|FA_DIREC); - if (done) { - PyErr_Format(PyExc_NameError, - "Can't find file for module %.100s\n(filename %.300s)", - name, buf); - return -1; - } - return strncmp(ffblk.ff_name, name, namelen) == 0; - -/* new-fangled macintosh (macosx) or Cygwin */ -#elif (defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) - DIR *dirp; - struct dirent *dp; - char dirname[MAXPATHLEN + 1]; - const int dirlen = len - namelen - 1; /* don't want trailing SEP */ - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - /* Copy the dir component into dirname; substitute "." if empty */ - if (dirlen <= 0) { - dirname[0] = '.'; - dirname[1] = '\0'; - } - else { - assert(dirlen <= MAXPATHLEN); - memcpy(dirname, buf, dirlen); - dirname[dirlen] = '\0'; - } - /* Open the directory and search the entries for an exact match. */ - dirp = opendir(dirname); - if (dirp) { - char *nameWithExt = buf + len - namelen; - while ((dp = readdir(dirp)) != NULL) { - const int thislen = -#ifdef _DIRENT_HAVE_D_NAMELEN - dp->d_namlen; -#else - strlen(dp->d_name); -#endif - if (thislen >= namelen && - strcmp(dp->d_name, nameWithExt) == 0) { - (void)closedir(dirp); - return 1; /* Found */ - } - } - (void)closedir(dirp); - } - return 0 ; /* Not found */ - -/* OS/2 */ -#elif defined(PYOS_OS2) - HDIR hdir = 1; - ULONG srchcnt = 1; - FILEFINDBUF3 ffbuf; - APIRET rc; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - rc = DosFindFirst(buf, - &hdir, - FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY, - &ffbuf, sizeof(ffbuf), - &srchcnt, - FIL_STANDARD); - if (rc != NO_ERROR) - return 0; - return strncmp(ffbuf.achName, name, namelen) == 0; - -/* assuming it's a case-sensitive filesystem, so there's nothing to do! */ -#else -# error "USE_CASE_OK_BYTES is not correctly defined" -#endif -} -#endif - -/* - * Check if a filename case matchs the name case. We've already done a - * successful stat() or fopen() on buf, so know that there's some match, - * possibly case-insensitive. - * - * case_ok() is to return 1 if there's a case-sensitive match for name, 0 if it - * the filename doesn't match, or -1 on error. case_ok() is also to return 1 - * if envar PYTHONCASEOK exists. - * - * case_ok() is used to implement case-sensitive import semantics even - * on platforms with case-insensitive filesystems. It's trivial to implement - * for case-sensitive filesystems. It's pretty much a cross-platform - * nightmare for systems with case-insensitive filesystems. - */ - -static int -case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) -{ -#ifdef MS_WINDOWS - WIN32_FIND_DATAW data; - HANDLE h; - int cmp; - wchar_t *wfilename, *wname; - Py_ssize_t wname_len; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - wfilename = PyUnicode_AsUnicode(filename); - if (wfilename == NULL) - return -1; - - h = FindFirstFileW(wfilename, &data); - if (h == INVALID_HANDLE_VALUE) { - PyErr_Format(PyExc_NameError, - "Can't find file for module %R\n(filename %R)", - name, filename); - return -1; - } - FindClose(h); - - wname = PyUnicode_AsUnicodeAndSize(name, &wname_len); - if (wname == NULL) - return -1; - - cmp = wcsncmp(data.cFileName, wname, wname_len); - return cmp == 0; -#elif defined(USE_CASE_OK_BYTES) - int match; - PyObject *filebytes, *namebytes; - filebytes = PyUnicode_EncodeFSDefault(filename); - if (filebytes == NULL) - return -1; - namebytes = PyUnicode_EncodeFSDefault(name); - if (namebytes == NULL) { - Py_DECREF(filebytes); - return -1; - } - match = case_bytes( - PyBytes_AS_STRING(filebytes), - PyBytes_GET_SIZE(filebytes) + prefix_delta, - PyBytes_GET_SIZE(namebytes), - PyBytes_AS_STRING(namebytes)); - Py_DECREF(filebytes); - Py_DECREF(namebytes); - return match; -#else - /* assuming it's a case-sensitive filesystem, so there's nothing to do! */ - return 1; - -#endif -} - -#ifdef HAVE_STAT - -/* Helper to look for __init__.py or __init__.py[co] in potential package. - Return 1 if __init__ was found, 0 if not, or -1 on error. */ -static int -find_init_module(PyObject *directory) -{ - struct stat statbuf; - PyObject *filename; - int match; - int err; - - filename = PyUnicode_FromFormat("%U%c__init__.py", directory, SEP); - if (filename == NULL) - return -1; - err = _Py_stat(filename, &statbuf); - if (err == -2) - return -1; - if (err == 0) { - /* 3=len(".py") */ - match = case_ok(filename, -3, initstr); - if (match < 0) { - Py_DECREF(filename); - return -1; - } - if (match) { - Py_DECREF(filename); - return 1; - } - } - Py_DECREF(filename); - - filename = PyUnicode_FromFormat("%U%c__init__.py%c", - directory, SEP, Py_OptimizeFlag ? 'o' : 'c'); - if (filename == NULL) - return -1; - err = _Py_stat(filename, &statbuf); - if (err == -2) { - Py_DECREF(filename); - return -1; - } - if (err == 0) { - /* 4=len(".pyc") */ - match = case_ok(filename, -4, initstr); - if (match < 0) { - Py_DECREF(filename); - return -1; - } - if (match) { - Py_DECREF(filename); - return 1; - } - } - Py_DECREF(filename); - return 0; -} - -#endif /* HAVE_STAT */ - static int init_builtin(PyObject *); /* Forward */ @@ -2689,81 +2021,6 @@ } static PyObject * -call_find_module(PyObject *name, PyObject *path_list) -{ - extern int fclose(FILE *); - PyObject *fob, *ret; - PyObject *pathobj; - struct filedescr *fdp; - FILE *fp; - int fd = -1; - char *found_encoding = NULL; - char *encoding = NULL; - - if (path_list == Py_None) - path_list = NULL; - fdp = find_module(NULL, name, path_list, - &pathobj, &fp, NULL); - if (fdp == NULL) - return NULL; - if (fp != NULL) { - fd = fileno(fp); - if (fd != -1) - fd = dup(fd); - fclose(fp); - fp = NULL; - if (fd == -1) - return PyErr_SetFromErrno(PyExc_OSError); - } - if (fd != -1) { - if (strchr(fdp->mode, 'b') == NULL) { - /* PyTokenizer_FindEncodingFilename() returns PyMem_MALLOC'ed - memory. */ - found_encoding = PyTokenizer_FindEncodingFilename(fd, pathobj); - lseek(fd, 0, 0); /* Reset position */ - if (found_encoding == NULL && PyErr_Occurred()) { - Py_XDECREF(pathobj); - close(fd); - return NULL; - } - encoding = (found_encoding != NULL) ? found_encoding : - (char*)PyUnicode_GetDefaultEncoding(); - } - fob = PyFile_FromFd(fd, NULL, fdp->mode, -1, - (char*)encoding, NULL, NULL, 1); - if (fob == NULL) { - Py_XDECREF(pathobj); - close(fd); - PyMem_FREE(found_encoding); - return NULL; - } - } - else { - fob = Py_None; - Py_INCREF(fob); - } - if (pathobj == NULL) { - Py_INCREF(Py_None); - pathobj = Py_None; - } - ret = Py_BuildValue("NN(ssi)", - fob, pathobj, fdp->suffix, fdp->mode, fdp->type); - PyMem_FREE(found_encoding); - - return ret; -} - -static PyObject * -imp_find_module(PyObject *self, PyObject *args) -{ - PyObject *name, *path_list = NULL; - if (!PyArg_ParseTuple(args, "U|O:find_module", - &name, &path_list)) - return NULL; - return call_find_module(name, path_list); -} - -static PyObject * imp_init_builtin(PyObject *self, PyObject *args) { PyObject *name; @@ -2931,13 +2188,6 @@ PyDoc_STRVAR(doc_imp, "(Extremely) low-level import machinery bits as used by importlib and imp."); -PyDoc_STRVAR(doc_find_module, -"find_module(name, [path]) -> (file, filename, (suffix, mode, type))\n\ -Search for a module. If path is omitted or None, search for a\n\ -built-in, frozen or special module and continue search in sys.path.\n\ -The module name cannot contain '.'; to search for a submodule of a\n\ -package, pass the submodule name and the package's __path__."); - PyDoc_STRVAR(doc_get_magic, "get_magic() -> string\n\ Return the magic number for .pyc or .pyo files."); @@ -2969,7 +2219,6 @@ On platforms without threads, this function does nothing."); static PyMethodDef imp_methods[] = { - {"find_module", imp_find_module, METH_VARARGS, doc_find_module}, {"get_magic", imp_get_magic, METH_NOARGS, doc_get_magic}, {"get_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, {"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 03:15:34 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 03:15:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_whitespace=2E?= Message-ID: http://hg.python.org/cpython/rev/8fc44e3a6bfe changeset: 76456:8fc44e3a6bfe user: Brett Cannon date: Sat Apr 21 21:15:28 2012 -0400 summary: Fix whitespace. files: Lib/imp.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -194,4 +194,3 @@ encoding = tokenize.detect_encoding(file.readline)[0] file = open(file_path, mode, encoding=encoding) return file, file_path, (suffix, mode, type_) - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 03:20:01 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 22 Apr 2012 03:20:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_Issue2193_-_Allow_=22?= =?utf8?q?=3A=22_character_in_Cookie_NAME_values?= Message-ID: http://hg.python.org/cpython/rev/57ec2e6cd70a changeset: 76457:57ec2e6cd70a parent: 76454:0356103cde28 user: Senthil Kumaran date: Sun Apr 22 09:19:04 2012 +0800 summary: Fix Issue2193 - Allow ":" character in Cookie NAME values files: Lib/http/cookies.py | 2 +- Lib/test/test_http_cookies.py | 9 +++++++++ Misc/NEWS | 2 ++ 3 files changed, 12 insertions(+), 1 deletions(-) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -159,7 +159,7 @@ # _LegalChars is the list of chars which don't require "'s # _Translator hash-table for fast quoting # -_LegalChars = string.ascii_letters + string.digits + "!#$%&'*+-.^_`|~" +_LegalChars = string.ascii_letters + string.digits + "!#$%&'*+-.^_`|~:" _Translator = { '\000' : '\\000', '\001' : '\\001', '\002' : '\\002', '\003' : '\\003', '\004' : '\\004', '\005' : '\\005', diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -34,6 +34,15 @@ 'dict': {'keebler' : 'E=mc2'}, 'repr': "", 'output': 'Set-Cookie: keebler=E=mc2'}, + + # Cookies with ':' character in their name. Though not mentioned in + # RFC, servers / browsers allow it. + + {'data': 'key:term=value:term', + 'dict': {'key:term' : 'value:term'}, + 'repr': "", + 'output': 'Set-Cookie: key:term=value:term'}, + ] for case in cases: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,8 @@ Library ------- +- Issue #2193: Allow ":" character in Cookie NAME values. + - Issue #14629: tokenizer.detect_encoding will specify the filename in the SyntaxError exception if found at readline.__self__.name. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 03:20:02 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 22 Apr 2012 03:20:02 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/943e0520476f changeset: 76458:943e0520476f parent: 76457:57ec2e6cd70a parent: 76456:8fc44e3a6bfe user: Senthil Kumaran date: Sun Apr 22 09:19:49 2012 +0800 summary: merge heads files: Lib/imp.py | 71 +++- Python/import.c | 751 ------------------------------------ 2 files changed, 67 insertions(+), 755 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -15,16 +15,29 @@ # Can (probably) move to importlib from _imp import get_suffixes # Should be re-implemented here (and mostly deprecated) -from _imp import (find_module, NullImporter, - SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, - PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, - PY_CODERESOURCE, IMP_HOOK) +from _imp import NullImporter from importlib._bootstrap import _new_module as new_module from importlib._bootstrap import _cache_from_source as cache_from_source from importlib import _bootstrap import os +import sys +import tokenize + + +# XXX "deprecate" once find_module(), load_module(), and get_suffixes() are +# deprecated. +SEARCH_ERROR = 0 +PY_SOURCE = 1 +PY_COMPILED = 2 +C_EXTENSION = 3 +PY_RESOURCE = 4 +PKG_DIRECTORY = 5 +C_BUILTIN = 6 +PY_FROZEN = 7 +PY_CODERESOURCE = 8 +IMP_HOOK = 9 def source_from_cache(path): @@ -131,3 +144,53 @@ else: msg = "Don't know how to import {} (type code {}".format(name, type_) raise ImportError(msg, name=name) + + +def find_module(name, path=None): + """Search for a module. + + If path is omitted or None, search for a built-in, frozen or special + module and continue search in sys.path. The module name cannot + contain '.'; to search for a submodule of a package, pass the + submodule name and the package's __path__. + + """ + if not isinstance(name, str): + raise TypeError("'name' must be a str, not {}".format(type(name))) + elif not isinstance(path, (type(None), list)): + # Backwards-compatibility + raise RuntimeError("'list' must be None or a list, " + "not {}".format(type(name))) + + if path is None: + if is_builtin(name): + return None, None, ('', '', C_BUILTIN) + elif is_frozen(name): + return None, None, ('', '', PY_FROZEN) + else: + path = sys.path + + for entry in path: + package_directory = os.path.join(entry, name) + for suffix in ['.py', _bootstrap.BYTECODE_SUFFIX]: + package_file_name = '__init__' + suffix + file_path = os.path.join(package_directory, package_file_name) + if os.path.isfile(file_path): + return None, package_directory, ('', '', PKG_DIRECTORY) + for suffix, mode, type_ in get_suffixes(): + file_name = name + suffix + file_path = os.path.join(entry, file_name) + if os.path.isfile(file_path): + break + else: + continue + break # Break out of outer loop when breaking out of inner loop. + else: + raise ImportError('No module name {!r}'.format(name), name=name) + + encoding = None + if mode == 'U': + with open(file_path, 'rb') as file: + encoding = tokenize.detect_encoding(file.readline)[0] + file = open(file_path, mode, encoding=encoding) + return file, file_path, (suffix, mode, type_) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1118,8 +1118,6 @@ } /* Forward */ -static struct filedescr *find_module(PyObject *, PyObject *, PyObject *, - PyObject **, FILE **, PyObject **); static struct _frozen * find_frozen(PyObject *); @@ -1220,678 +1218,12 @@ return importer; } -/* Search the path (default sys.path) for a module. Return the - corresponding filedescr struct, and (via return arguments) the - pathname and an open file. Return NULL if the module is not found. */ #ifdef MS_COREDLL extern FILE *_PyWin_FindRegisteredModule(PyObject *, struct filedescr **, PyObject **p_path); #endif -/* Forward */ -static int case_ok(PyObject *, Py_ssize_t, PyObject *); -static int find_init_module(PyObject *); -static struct filedescr importhookdescr = {"", "", IMP_HOOK}; - -/* Get the path of a module: get its importer and call importer.find_module() - hook, or check if the module if a package (if path/__init__.py exists). - - -1: error: a Python error occurred - 0: ignore: an error occurred because of invalid data, but the error is not - important enough to be reported. - 1: get path: module not found, but *buf contains its path - 2: found: *p_fd is the file descriptor (IMP_HOOK or PKG_DIRECTORY) - and *buf is the path */ - -static int -find_module_path(PyObject *fullname, PyObject *name, PyObject *path, - PyObject *path_hooks, PyObject *path_importer_cache, - PyObject **p_path, PyObject **p_loader, struct filedescr **p_fd) -{ - PyObject *path_unicode, *filename = NULL; - Py_ssize_t len, pos; - struct stat statbuf; - static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; - int err, result, addsep; - - if (PyUnicode_Check(path)) { - Py_INCREF(path); - path_unicode = path; - } - else if (PyBytes_Check(path)) { - path_unicode = PyUnicode_DecodeFSDefaultAndSize( - PyBytes_AS_STRING(path), PyBytes_GET_SIZE(path)); - if (path_unicode == NULL) - return -1; - } - else - return 0; - - if (PyUnicode_READY(path_unicode)) - return -1; - - len = PyUnicode_GET_LENGTH(path_unicode); - if (PyUnicode_FindChar(path_unicode, 0, 0, len, 1) != -1) { - result = 0; - goto out; /* path contains '\0' */ - } - - /* sys.path_hooks import hook */ - if (p_loader != NULL) { - _Py_IDENTIFIER(find_module); - PyObject *importer; - - importer = get_path_importer(path_importer_cache, - path_hooks, path); - if (importer == NULL) { - result = -1; - goto out; - } - /* Note: importer is a borrowed reference */ - if (importer != Py_None) { - PyObject *loader; - loader = _PyObject_CallMethodId(importer, - &PyId_find_module, "O", fullname); - if (loader == NULL) { - result = -1; /* error */ - goto out; - } - if (loader != Py_None) { - /* a loader was found */ - *p_loader = loader; - *p_fd = &importhookdescr; - result = 2; - goto out; - } - Py_DECREF(loader); - result = 0; - goto out; - } - } - /* no hook was found, use builtin import */ - - addsep = 0; - if (len > 0 && PyUnicode_READ_CHAR(path_unicode, len-1) != SEP -#ifdef ALTSEP - && PyUnicode_READ_CHAR(path_unicode, len-1) != ALTSEP -#endif - ) - addsep = 1; - filename = PyUnicode_New(len + PyUnicode_GET_LENGTH(name) + addsep, - Py_MAX(PyUnicode_MAX_CHAR_VALUE(path_unicode), - PyUnicode_MAX_CHAR_VALUE(name))); - if (filename == NULL) { - result = -1; - goto out; - } - PyUnicode_CopyCharacters(filename, 0, path_unicode, 0, len); - pos = len; - if (addsep) - PyUnicode_WRITE(PyUnicode_KIND(filename), - PyUnicode_DATA(filename), - pos++, SEP); - PyUnicode_CopyCharacters(filename, pos, name, 0, - PyUnicode_GET_LENGTH(name)); - - /* Check for package import (buf holds a directory name, - and there's an __init__ module in that directory */ -#ifdef HAVE_STAT - err = _Py_stat(filename, &statbuf); - if (err == -2) { - result = -1; - goto out; - } - if (err == 0 && /* it exists */ - S_ISDIR(statbuf.st_mode)) /* it's a directory */ - { - int match; - - match = case_ok(filename, 0, name); - if (match < 0) { - result = -1; - goto out; - } - if (match) { /* case matches */ - if (find_init_module(filename)) { /* and has __init__.py */ - *p_path = filename; - filename = NULL; - *p_fd = &fd_package; - result = 2; - goto out; - } - else { - int err; - err = PyErr_WarnFormat(PyExc_ImportWarning, 1, - "Not importing directory %R: missing __init__.py", - filename); - if (err) { - result = -1; - goto out; - } - } - } - } -#endif - *p_path = filename; - filename = NULL; - result = 1; - out: - Py_DECREF(path_unicode); - Py_XDECREF(filename); - return result; -} - -/* Find a module in search_path_list. For each path, try - find_module_path() or try each _PyImport_Filetab suffix. - - If the module is found, return a file descriptor, write the path in - *p_filename, write the pointer to the file object into *p_fp, and (if - p_loader is not NULL) the loader into *p_loader. - - Otherwise, raise an exception and return NULL. */ - -static struct filedescr* -find_module_path_list(PyObject *fullname, PyObject *name, - PyObject *search_path_list, PyObject *path_hooks, - PyObject *path_importer_cache, - PyObject **p_path, FILE **p_fp, PyObject **p_loader) -{ - Py_ssize_t i, npath; - struct filedescr *fdp = NULL; - char *filemode; - FILE *fp = NULL; - PyObject *prefix, *filename; - int match; - int err; - - npath = PyList_Size(search_path_list); - for (i = 0; i < npath; i++) { - PyObject *path; - int ok; - - path = PyList_GetItem(search_path_list, i); - if (path == NULL) - return NULL; - - prefix = NULL; - ok = find_module_path(fullname, name, path, - path_hooks, path_importer_cache, - &prefix, p_loader, &fdp); - if (ok < 0) - return NULL; - if (ok == 0) - continue; - if (ok == 2) { - *p_path = prefix; - return fdp; - } - - for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { - struct stat statbuf; - - filemode = fdp->mode; - if (filemode[0] == 'U') - filemode = "r" PY_STDIOTEXTMODE; - - filename = PyUnicode_FromFormat("%U%s", prefix, fdp->suffix); - if (filename == NULL) { - Py_DECREF(prefix); - return NULL; - } - - if (Py_VerboseFlag > 1) - PySys_FormatStderr("# trying %R\n", filename); - - err = _Py_stat(filename, &statbuf); - if (err == -2) { - Py_DECREF(prefix); - Py_DECREF(filename); - return NULL; - } - if (err != 0 || S_ISDIR(statbuf.st_mode)) { - /* it doesn't exist, or it's a directory */ - Py_DECREF(filename); - continue; - } - - fp = _Py_fopen(filename, filemode); - if (fp == NULL) { - Py_DECREF(filename); - if (PyErr_Occurred()) { - Py_DECREF(prefix); - return NULL; - } - continue; - } - match = case_ok(filename, -(Py_ssize_t)strlen(fdp->suffix), name); - if (match < 0) { - Py_DECREF(prefix); - Py_DECREF(filename); - return NULL; - } - if (match) { - Py_DECREF(prefix); - *p_path = filename; - *p_fp = fp; - return fdp; - } - Py_DECREF(filename); - - fclose(fp); - fp = NULL; - } - Py_DECREF(prefix); - } - PyErr_Format(PyExc_ImportError, - "No module named %R", name); - return NULL; -} - -/* Find a module: - - - try find_module() of each sys.meta_path hook - - try find_frozen() - - try is_builtin() - - try _PyWin_FindRegisteredModule() (Windows only) - - otherwise, call find_module_path_list() with search_path_list (if not - NULL) or sys.path - - fullname can be NULL, but only if p_loader is NULL. - - Return: - - - &fd_builtin (C_BUILTIN) if it is a builtin - - &fd_frozen (PY_FROZEN) if it is frozen - - &fd_package (PKG_DIRECTORY) and write the filename into *p_path - if it is a package - - &importhookdescr (IMP_HOOK) and write the loader into *p_loader if a - importer loader was found - - a file descriptor (PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE or - PY_CODERESOURCE: see _PyImport_Filetab), write the filename into - *p_path and the pointer to the open file into *p_fp - - NULL on error - - By default, *p_path, *p_fp and *p_loader (if set) are set to NULL. - Eg. *p_path is set to NULL for a builtin package. -*/ - -static struct filedescr * -find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, - PyObject **p_path, FILE **p_fp, PyObject **p_loader) -{ - Py_ssize_t i, npath; - static struct filedescr fd_frozen = {"", "", PY_FROZEN}; - static struct filedescr fd_builtin = {"", "", C_BUILTIN}; - PyObject *path_hooks, *path_importer_cache; - - *p_path = NULL; - *p_fp = NULL; - if (p_loader != NULL) - *p_loader = NULL; - - /* sys.meta_path import hook */ - if (p_loader != NULL) { - _Py_IDENTIFIER(find_module); - PyObject *meta_path; - - meta_path = PySys_GetObject("meta_path"); - if (meta_path == NULL || !PyList_Check(meta_path)) { - PyErr_SetString(PyExc_RuntimeError, - "sys.meta_path must be a list of " - "import hooks"); - return NULL; - } - Py_INCREF(meta_path); /* zap guard */ - npath = PyList_Size(meta_path); - for (i = 0; i < npath; i++) { - PyObject *loader; - PyObject *hook = PyList_GetItem(meta_path, i); - loader = _PyObject_CallMethodId(hook, &PyId_find_module, - "OO", fullname, - search_path_list != NULL ? - search_path_list : Py_None); - if (loader == NULL) { - Py_DECREF(meta_path); - return NULL; /* true error */ - } - if (loader != Py_None) { - /* a loader was found */ - *p_loader = loader; - Py_DECREF(meta_path); - return &importhookdescr; - } - Py_DECREF(loader); - } - Py_DECREF(meta_path); - } - - if (find_frozen(fullname) != NULL) - return &fd_frozen; - - if (search_path_list == NULL) { -#ifdef MS_COREDLL - FILE *fp; - struct filedescr *fdp; -#endif - if (is_builtin(name)) - return &fd_builtin; -#ifdef MS_COREDLL - fp = _PyWin_FindRegisteredModule(name, &fdp, p_path); - if (fp != NULL) { - *p_fp = fp; - return fdp; - } - else if (PyErr_Occurred()) - return NULL; -#endif - search_path_list = PySys_GetObject("path"); - } - - if (search_path_list == NULL || !PyList_Check(search_path_list)) { - PyErr_SetString(PyExc_RuntimeError, - "sys.path must be a list of directory names"); - return NULL; - } - - path_hooks = PySys_GetObject("path_hooks"); - if (path_hooks == NULL || !PyList_Check(path_hooks)) { - PyErr_SetString(PyExc_RuntimeError, - "sys.path_hooks must be a list of " - "import hooks"); - return NULL; - } - path_importer_cache = PySys_GetObject("path_importer_cache"); - if (path_importer_cache == NULL || - !PyDict_Check(path_importer_cache)) { - PyErr_SetString(PyExc_RuntimeError, - "sys.path_importer_cache must be a dict"); - return NULL; - } - - return find_module_path_list(fullname, name, - search_path_list, path_hooks, - path_importer_cache, - p_path, p_fp, p_loader); -} - -/* case_bytes(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name) - * The arguments here are tricky, best shown by example: - * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0 - * ^ ^ ^ ^ - * |--------------------- buf ---------------------| - * |------------------- len ------------------| - * |------ name -------| - * |----- namelen -----| - * buf is the full path, but len only counts up to (& exclusive of) the - * extension. name is the module name, also exclusive of extension. - * - * We've already done a successful stat() or fopen() on buf, so know that - * there's some match, possibly case-insensitive. - * - * case_bytes() is to return 1 if there's a case-sensitive match for - * name, else 0. case_bytes() is also to return 1 if envar PYTHONCASEOK - * exists. - * - * case_bytes() is used to implement case-sensitive import semantics even - * on platforms with case-insensitive filesystems. It's trivial to implement - * for case-sensitive filesystems. It's pretty much a cross-platform - * nightmare for systems with case-insensitive filesystems. - */ - -/* First we may need a pile of platform-specific header files; the sequence - * of #if's here should match the sequence in the body of case_bytes(). - */ -#if defined(MS_WINDOWS) -#include - -#elif defined(DJGPP) -#include - -#elif (defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) -#include -#include - -#elif defined(PYOS_OS2) -#define INCL_DOS -#define INCL_DOSERRORS -#define INCL_NOPMAPI -#include -#endif - -#if defined(DJGPP) \ - || ((defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) \ - && defined(HAVE_DIRENT_H)) \ - || defined(PYOS_OS2) -# define USE_CASE_OK_BYTES -#endif - - -#ifdef USE_CASE_OK_BYTES -static int -case_bytes(char *buf, Py_ssize_t len, Py_ssize_t namelen, const char *name) -{ -/* Pick a platform-specific implementation; the sequence of #if's here should - * match the sequence just above. - */ - -/* DJGPP */ -#if defined(DJGPP) - struct ffblk ffblk; - int done; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - done = findfirst(buf, &ffblk, FA_ARCH|FA_RDONLY|FA_HIDDEN|FA_DIREC); - if (done) { - PyErr_Format(PyExc_NameError, - "Can't find file for module %.100s\n(filename %.300s)", - name, buf); - return -1; - } - return strncmp(ffblk.ff_name, name, namelen) == 0; - -/* new-fangled macintosh (macosx) or Cygwin */ -#elif (defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) - DIR *dirp; - struct dirent *dp; - char dirname[MAXPATHLEN + 1]; - const int dirlen = len - namelen - 1; /* don't want trailing SEP */ - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - /* Copy the dir component into dirname; substitute "." if empty */ - if (dirlen <= 0) { - dirname[0] = '.'; - dirname[1] = '\0'; - } - else { - assert(dirlen <= MAXPATHLEN); - memcpy(dirname, buf, dirlen); - dirname[dirlen] = '\0'; - } - /* Open the directory and search the entries for an exact match. */ - dirp = opendir(dirname); - if (dirp) { - char *nameWithExt = buf + len - namelen; - while ((dp = readdir(dirp)) != NULL) { - const int thislen = -#ifdef _DIRENT_HAVE_D_NAMELEN - dp->d_namlen; -#else - strlen(dp->d_name); -#endif - if (thislen >= namelen && - strcmp(dp->d_name, nameWithExt) == 0) { - (void)closedir(dirp); - return 1; /* Found */ - } - } - (void)closedir(dirp); - } - return 0 ; /* Not found */ - -/* OS/2 */ -#elif defined(PYOS_OS2) - HDIR hdir = 1; - ULONG srchcnt = 1; - FILEFINDBUF3 ffbuf; - APIRET rc; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - rc = DosFindFirst(buf, - &hdir, - FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY, - &ffbuf, sizeof(ffbuf), - &srchcnt, - FIL_STANDARD); - if (rc != NO_ERROR) - return 0; - return strncmp(ffbuf.achName, name, namelen) == 0; - -/* assuming it's a case-sensitive filesystem, so there's nothing to do! */ -#else -# error "USE_CASE_OK_BYTES is not correctly defined" -#endif -} -#endif - -/* - * Check if a filename case matchs the name case. We've already done a - * successful stat() or fopen() on buf, so know that there's some match, - * possibly case-insensitive. - * - * case_ok() is to return 1 if there's a case-sensitive match for name, 0 if it - * the filename doesn't match, or -1 on error. case_ok() is also to return 1 - * if envar PYTHONCASEOK exists. - * - * case_ok() is used to implement case-sensitive import semantics even - * on platforms with case-insensitive filesystems. It's trivial to implement - * for case-sensitive filesystems. It's pretty much a cross-platform - * nightmare for systems with case-insensitive filesystems. - */ - -static int -case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) -{ -#ifdef MS_WINDOWS - WIN32_FIND_DATAW data; - HANDLE h; - int cmp; - wchar_t *wfilename, *wname; - Py_ssize_t wname_len; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - wfilename = PyUnicode_AsUnicode(filename); - if (wfilename == NULL) - return -1; - - h = FindFirstFileW(wfilename, &data); - if (h == INVALID_HANDLE_VALUE) { - PyErr_Format(PyExc_NameError, - "Can't find file for module %R\n(filename %R)", - name, filename); - return -1; - } - FindClose(h); - - wname = PyUnicode_AsUnicodeAndSize(name, &wname_len); - if (wname == NULL) - return -1; - - cmp = wcsncmp(data.cFileName, wname, wname_len); - return cmp == 0; -#elif defined(USE_CASE_OK_BYTES) - int match; - PyObject *filebytes, *namebytes; - filebytes = PyUnicode_EncodeFSDefault(filename); - if (filebytes == NULL) - return -1; - namebytes = PyUnicode_EncodeFSDefault(name); - if (namebytes == NULL) { - Py_DECREF(filebytes); - return -1; - } - match = case_bytes( - PyBytes_AS_STRING(filebytes), - PyBytes_GET_SIZE(filebytes) + prefix_delta, - PyBytes_GET_SIZE(namebytes), - PyBytes_AS_STRING(namebytes)); - Py_DECREF(filebytes); - Py_DECREF(namebytes); - return match; -#else - /* assuming it's a case-sensitive filesystem, so there's nothing to do! */ - return 1; - -#endif -} - -#ifdef HAVE_STAT - -/* Helper to look for __init__.py or __init__.py[co] in potential package. - Return 1 if __init__ was found, 0 if not, or -1 on error. */ -static int -find_init_module(PyObject *directory) -{ - struct stat statbuf; - PyObject *filename; - int match; - int err; - - filename = PyUnicode_FromFormat("%U%c__init__.py", directory, SEP); - if (filename == NULL) - return -1; - err = _Py_stat(filename, &statbuf); - if (err == -2) - return -1; - if (err == 0) { - /* 3=len(".py") */ - match = case_ok(filename, -3, initstr); - if (match < 0) { - Py_DECREF(filename); - return -1; - } - if (match) { - Py_DECREF(filename); - return 1; - } - } - Py_DECREF(filename); - - filename = PyUnicode_FromFormat("%U%c__init__.py%c", - directory, SEP, Py_OptimizeFlag ? 'o' : 'c'); - if (filename == NULL) - return -1; - err = _Py_stat(filename, &statbuf); - if (err == -2) { - Py_DECREF(filename); - return -1; - } - if (err == 0) { - /* 4=len(".pyc") */ - match = case_ok(filename, -4, initstr); - if (match < 0) { - Py_DECREF(filename); - return -1; - } - if (match) { - Py_DECREF(filename); - return 1; - } - } - Py_DECREF(filename); - return 0; -} - -#endif /* HAVE_STAT */ - static int init_builtin(PyObject *); /* Forward */ @@ -2689,81 +2021,6 @@ } static PyObject * -call_find_module(PyObject *name, PyObject *path_list) -{ - extern int fclose(FILE *); - PyObject *fob, *ret; - PyObject *pathobj; - struct filedescr *fdp; - FILE *fp; - int fd = -1; - char *found_encoding = NULL; - char *encoding = NULL; - - if (path_list == Py_None) - path_list = NULL; - fdp = find_module(NULL, name, path_list, - &pathobj, &fp, NULL); - if (fdp == NULL) - return NULL; - if (fp != NULL) { - fd = fileno(fp); - if (fd != -1) - fd = dup(fd); - fclose(fp); - fp = NULL; - if (fd == -1) - return PyErr_SetFromErrno(PyExc_OSError); - } - if (fd != -1) { - if (strchr(fdp->mode, 'b') == NULL) { - /* PyTokenizer_FindEncodingFilename() returns PyMem_MALLOC'ed - memory. */ - found_encoding = PyTokenizer_FindEncodingFilename(fd, pathobj); - lseek(fd, 0, 0); /* Reset position */ - if (found_encoding == NULL && PyErr_Occurred()) { - Py_XDECREF(pathobj); - close(fd); - return NULL; - } - encoding = (found_encoding != NULL) ? found_encoding : - (char*)PyUnicode_GetDefaultEncoding(); - } - fob = PyFile_FromFd(fd, NULL, fdp->mode, -1, - (char*)encoding, NULL, NULL, 1); - if (fob == NULL) { - Py_XDECREF(pathobj); - close(fd); - PyMem_FREE(found_encoding); - return NULL; - } - } - else { - fob = Py_None; - Py_INCREF(fob); - } - if (pathobj == NULL) { - Py_INCREF(Py_None); - pathobj = Py_None; - } - ret = Py_BuildValue("NN(ssi)", - fob, pathobj, fdp->suffix, fdp->mode, fdp->type); - PyMem_FREE(found_encoding); - - return ret; -} - -static PyObject * -imp_find_module(PyObject *self, PyObject *args) -{ - PyObject *name, *path_list = NULL; - if (!PyArg_ParseTuple(args, "U|O:find_module", - &name, &path_list)) - return NULL; - return call_find_module(name, path_list); -} - -static PyObject * imp_init_builtin(PyObject *self, PyObject *args) { PyObject *name; @@ -2931,13 +2188,6 @@ PyDoc_STRVAR(doc_imp, "(Extremely) low-level import machinery bits as used by importlib and imp."); -PyDoc_STRVAR(doc_find_module, -"find_module(name, [path]) -> (file, filename, (suffix, mode, type))\n\ -Search for a module. If path is omitted or None, search for a\n\ -built-in, frozen or special module and continue search in sys.path.\n\ -The module name cannot contain '.'; to search for a submodule of a\n\ -package, pass the submodule name and the package's __path__."); - PyDoc_STRVAR(doc_get_magic, "get_magic() -> string\n\ Return the magic number for .pyc or .pyo files."); @@ -2969,7 +2219,6 @@ On platforms without threads, this function does nothing."); static PyMethodDef imp_methods[] = { - {"find_module", imp_find_module, METH_VARARGS, doc_find_module}, {"get_magic", imp_get_magic, METH_NOARGS, doc_get_magic}, {"get_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, {"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 03:22:01 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 03:22:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Have_importlib_look_for_pre?= =?utf8?q?-existing_path_separators_when_joining?= Message-ID: http://hg.python.org/cpython/rev/b8cd8dd7006a changeset: 76459:b8cd8dd7006a parent: 76456:8fc44e3a6bfe user: Brett Cannon date: Sat Apr 21 21:21:27 2012 -0400 summary: Have importlib look for pre-existing path separators when joining paths. files: Lib/importlib/_bootstrap.py | 12 ++++++++++-- Python/importlib.h | Bin 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -63,8 +63,16 @@ def _path_join(*args): """Replacement for os.path.join().""" - sep = path_sep if args[0][-1:] not in path_separators else args[0][-1] - return sep.join(x[:-len(path_sep)] if x.endswith(path_sep) else x + if len(path_separators) == 1: + sep = path_sep + else: + for c in reversed(args[0]): + if x in path_separators: + sep = x + break + else: + sep = path_sep + return sep.join(x[:-len(sep)] if x.endswith(sep) else x for x in args if x) diff --git a/Python/importlib.h b/Python/importlib.h index c48b5507699c679b7353d7e96ca9f4965da97c5b..115a5a9f7c0341a34b9f77989fcf0c2c82dcd95b GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 03:22:04 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 03:22:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/79f55cf917fd changeset: 76460:79f55cf917fd parent: 76459:b8cd8dd7006a parent: 76458:943e0520476f user: Brett Cannon date: Sat Apr 21 21:21:54 2012 -0400 summary: merge files: Lib/http/cookies.py | 2 +- Lib/test/test_http_cookies.py | 9 +++++++++ Misc/NEWS | 2 ++ 3 files changed, 12 insertions(+), 1 deletions(-) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -159,7 +159,7 @@ # _LegalChars is the list of chars which don't require "'s # _Translator hash-table for fast quoting # -_LegalChars = string.ascii_letters + string.digits + "!#$%&'*+-.^_`|~" +_LegalChars = string.ascii_letters + string.digits + "!#$%&'*+-.^_`|~:" _Translator = { '\000' : '\\000', '\001' : '\\001', '\002' : '\\002', '\003' : '\\003', '\004' : '\\004', '\005' : '\\005', diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -34,6 +34,15 @@ 'dict': {'keebler' : 'E=mc2'}, 'repr': "", 'output': 'Set-Cookie: keebler=E=mc2'}, + + # Cookies with ':' character in their name. Though not mentioned in + # RFC, servers / browsers allow it. + + {'data': 'key:term=value:term', + 'dict': {'key:term' : 'value:term'}, + 'repr': "", + 'output': 'Set-Cookie: key:term=value:term'}, + ] for case in cases: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,8 @@ Library ------- +- Issue #2193: Allow ":" character in Cookie NAME values. + - Issue #14629: tokenizer.detect_encoding will specify the filename in the SyntaxError exception if found at readline.__self__.name. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 03:46:40 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 03:46:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Continue_the_good_fight_to_?= =?utf8?q?get_Windows_to_like_importlib_by_fixing_a?= Message-ID: http://hg.python.org/cpython/rev/8db0a54fae44 changeset: 76461:8db0a54fae44 user: Brett Cannon date: Sat Apr 21 21:46:32 2012 -0400 summary: Continue the good fight to get Windows to like importlib by fixing a variable name. files: Lib/importlib/_bootstrap.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -61,12 +61,14 @@ return x +# XXX Optimize for single-separator OSs by having two versions of this function +# and choosing in _setup(). def _path_join(*args): """Replacement for os.path.join().""" if len(path_separators) == 1: sep = path_sep else: - for c in reversed(args[0]): + for x in reversed(args[0]): if x in path_separators: sep = x break -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 03:47:33 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 03:47:33 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Update_importlib=2Eh?= Message-ID: http://hg.python.org/cpython/rev/0a63868c5e95 changeset: 76462:0a63868c5e95 user: Brett Cannon date: Sat Apr 21 21:47:08 2012 -0400 summary: Update importlib.h files: Python/importlib.h | Bin 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Python/importlib.h b/Python/importlib.h index 115a5a9f7c0341a34b9f77989fcf0c2c82dcd95b..ad3894d796364f2a220f4de85aae4a9a6141a724 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 04:32:14 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 22 Apr 2012 04:32:14 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Update_2=2E7_do?= =?utf8?q?cs_about_legal_characters_allowed_in_Cookie_name?= Message-ID: http://hg.python.org/cpython/rev/a8af49baa636 changeset: 76463:a8af49baa636 branch: 2.7 parent: 76420:ab9d6c4907e7 user: Senthil Kumaran date: Sun Apr 22 10:27:22 2012 +0800 summary: Update 2.7 docs about legal characters allowed in Cookie name files: Doc/library/cookie.rst | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/cookie.rst b/Doc/library/cookie.rst --- a/Doc/library/cookie.rst +++ b/Doc/library/cookie.rst @@ -22,8 +22,14 @@ The module formerly strictly applied the parsing rules described in the :rfc:`2109` and :rfc:`2068` specifications. It has since been discovered that -MSIE 3.0x doesn't follow the character rules outlined in those specs. As a -result, the parsing rules used are a bit less strict. +MSIE 3.0x doesn't follow the character rules outlined in those specs and also +many current day browsers and servers have relaxed parsing rules when comes to +Cookie handling. As a result, the parsing rules used are a bit less strict. + +The character set, :data:`string.ascii_letters`, :data:`string.digits` and +``!#$%&'*+-.^_`|~`` denote the set of valid characters allowed by this module +in Cookie name (as :attr:`~Morsel.key`). + .. note:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 04:32:15 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 22 Apr 2012 04:32:15 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_issue2193_-_Upd?= =?utf8?q?ate_3=2E2_docs_about_legal_characters_allowed_in_Cookie_name?= Message-ID: http://hg.python.org/cpython/rev/d3b0845a9253 changeset: 76464:d3b0845a9253 branch: 3.2 parent: 76440:cdcc6b489862 user: Senthil Kumaran date: Sun Apr 22 10:30:17 2012 +0800 summary: issue2193 - Update 3.2 docs about legal characters allowed in Cookie name files: Doc/library/http.cookies.rst | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -17,8 +17,14 @@ The module formerly strictly applied the parsing rules described in the :rfc:`2109` and :rfc:`2068` specifications. It has since been discovered that -MSIE 3.0x doesn't follow the character rules outlined in those specs. As a -result, the parsing rules used are a bit less strict. +MSIE 3.0x doesn't follow the character rules outlined in those specs and also +many current day browsers and servers have relaxed parsing rules when comes to +Cookie handling. As a result, the parsing rules used are a bit less strict. + +The character set, :data:`string.ascii_letters`, :data:`string.digits` and +``!#$%&'*+-.^_`|~`` denote the set of valid characters allowed by this module +in Cookie name (as :attr:`~Morsel.key`). + .. note:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 04:32:16 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 22 Apr 2012 04:32:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_issue2193_-_Update_docs_abo?= =?utf8?q?ut_the_legal_characters_allowed_in_Cookie_name?= Message-ID: http://hg.python.org/cpython/rev/8cae3ee7f691 changeset: 76465:8cae3ee7f691 parent: 76462:0a63868c5e95 user: Senthil Kumaran date: Sun Apr 22 10:31:52 2012 +0800 summary: issue2193 - Update docs about the legal characters allowed in Cookie name files: Doc/library/http.cookies.rst | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -17,8 +17,17 @@ The module formerly strictly applied the parsing rules described in the :rfc:`2109` and :rfc:`2068` specifications. It has since been discovered that -MSIE 3.0x doesn't follow the character rules outlined in those specs. As a -result, the parsing rules used are a bit less strict. +MSIE 3.0x doesn't follow the character rules outlined in those specs and also +many current day browsers and servers have relaxed parsing rules when comes to +Cookie handling. As a result, the parsing rules used are a bit less strict. + +The character set, :data:`string.ascii_letters`, :data:`string.digits` and +``!#$%&'*+-.^_`|~:`` denote the set of valid characters allowed by this module +in Cookie name (as :attr:`~Morsel.key`). + +.. versionchanged:: 3.3 + Allowed ':' as a valid Cookie name character. + .. note:: -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Apr 22 05:35:13 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 22 Apr 2012 05:35:13 +0200 Subject: [Python-checkins] Daily reference leaks (79f55cf917fd): sum=0 Message-ID: results for 79f55cf917fd on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/refloggsKO0J', '-x'] From python-checkins at python.org Sun Apr 22 08:06:55 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 08:06:55 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Revert_to_os=2Epath=2Ejoin?= =?utf8?q?=28=29_semantics_for_path_manipulation_in_importlib?= Message-ID: http://hg.python.org/cpython/rev/9adfe3c0fe48 changeset: 76466:9adfe3c0fe48 parent: 76462:0a63868c5e95 user: Brett Cannon date: Sun Apr 22 02:06:23 2012 -0400 summary: Revert to os.path.join() semantics for path manipulation in importlib which is different than what imp.cache_from_source() operates on. files: Lib/importlib/_bootstrap.py | 13 ++----------- Python/importlib.h | Bin 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -65,17 +65,8 @@ # and choosing in _setup(). def _path_join(*args): """Replacement for os.path.join().""" - if len(path_separators) == 1: - sep = path_sep - else: - for x in reversed(args[0]): - if x in path_separators: - sep = x - break - else: - sep = path_sep - return sep.join(x[:-len(sep)] if x.endswith(sep) else x - for x in args if x) + return path_sep.join(x[:-len(path_sep)] if x.endswith(path_sep) else x + for x in args if x) def _path_split(path): diff --git a/Python/importlib.h b/Python/importlib.h index ad3894d796364f2a220f4de85aae4a9a6141a724..c6c561892fde3e990890ac20ea41bc8e63ba372b GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 08:06:56 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 08:06:56 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/765ca3caee10 changeset: 76467:765ca3caee10 parent: 76466:9adfe3c0fe48 parent: 76465:8cae3ee7f691 user: Brett Cannon date: Sun Apr 22 02:06:48 2012 -0400 summary: merge files: Doc/library/http.cookies.rst | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -17,8 +17,17 @@ The module formerly strictly applied the parsing rules described in the :rfc:`2109` and :rfc:`2068` specifications. It has since been discovered that -MSIE 3.0x doesn't follow the character rules outlined in those specs. As a -result, the parsing rules used are a bit less strict. +MSIE 3.0x doesn't follow the character rules outlined in those specs and also +many current day browsers and servers have relaxed parsing rules when comes to +Cookie handling. As a result, the parsing rules used are a bit less strict. + +The character set, :data:`string.ascii_letters`, :data:`string.digits` and +``!#$%&'*+-.^_`|~:`` denote the set of valid characters allowed by this module +in Cookie name (as :attr:`~Morsel.key`). + +.. versionchanged:: 3.3 + Allowed ':' as a valid Cookie name character. + .. note:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 08:09:04 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 08:09:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Mention_the_backwards-incom?= =?utf8?q?patible_change_to?= Message-ID: http://hg.python.org/cpython/rev/4a12e8d32ac6 changeset: 76468:4a12e8d32ac6 user: Brett Cannon date: Sun Apr 22 02:08:59 2012 -0400 summary: Mention the backwards-incompatible change to imp.cache_from_source()/source_from_cache(). files: Misc/NEWS | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,11 @@ Library ------- +- Issue #13959: imp.cache_from_source()/source_from_cache() now follow + os.path.join()/split() semantics for path manipulation instead of its prior, + custom semantics of caring the right-most path separator forward in path + joining. + - Issue #2193: Allow ":" character in Cookie NAME values. - Issue #14629: tokenizer.detect_encoding will specify the filename in the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 09:17:37 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 22 Apr 2012 09:17:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Close_issue_=23?= =?utf8?q?14026_by_better_testing_sys=2Eargv_handling_in_test=5Fcmd=5Fline?= =?utf8?q?=5Fscript?= Message-ID: http://hg.python.org/cpython/rev/22f0044ea366 changeset: 76469:22f0044ea366 branch: 3.2 parent: 76464:d3b0845a9253 user: Nick Coghlan date: Sun Apr 22 17:11:33 2012 +1000 summary: Close issue #14026 by better testing sys.argv handling in test_cmd_line_script (patch by Jason Yeo) files: Lib/test/test_cmd_line_script.py | 11 ++++++++--- Misc/NEWS | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -13,6 +13,8 @@ verbose = support.verbose +example_args = ['test1', 'test2', 'test3'] + test_source = """\ # Script may be run with optimisation enabled, so don't rely on assert # statements being executed @@ -36,6 +38,9 @@ # Check the sys module import sys assertIdentical(globals(), sys.modules[__name__].__dict__) +from test import test_cmd_line_script +example_args_list = test_cmd_line_script.example_args +assertEqual(sys.argv[1:], example_args_list) print('sys.argv[0]==%a' % sys.argv[0]) print('sys.path[0]==%a' % sys.path[0]) # Check the working directory @@ -100,7 +105,7 @@ *cmd_line_switches): if not __debug__: cmd_line_switches += ('-' + 'O' * sys.flags.optimize,) - run_args = cmd_line_switches + (script_name,) + run_args = cmd_line_switches + (script_name,) + tuple(example_args) rc, out, err = assert_python_ok(*run_args) self._check_output(script_name, rc, out + err, expected_file, expected_argv0, expected_path0, expected_package) @@ -240,7 +245,7 @@ pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])") script_name = _make_test_script(pkg_dir, 'script') - rc, out, err = assert_python_ok('-m', 'test_pkg.script') + rc, out, err = assert_python_ok('-m', 'test_pkg.script', *example_args) if verbose > 1: print(out) expected = "init_argv0==%r" % '-m' @@ -270,7 +275,7 @@ with support.temp_cwd(path=script_dir): with open("-m", "w") as f: f.write("data") - rc, out, err = assert_python_ok('-m', 'other') + rc, out, err = assert_python_ok('-m', 'other', *example_args) self._check_output(script_name, rc, out, script_name, script_name, '', '') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -161,6 +161,9 @@ Tests ----- +- Issue #14026: In test_cmd_line_script, check that sys.argv is populated + correctly for the various invocation approaches (Patch by Jason Yeo) + - Issue #14032: Fix incorrect variable name in test_cmd_line_script debugging message (Patch by Jason Yeo) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 09:17:37 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 22 Apr 2012 09:17:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Resolve_=2314026_=28Merge_from_3=2E2=29?= Message-ID: http://hg.python.org/cpython/rev/ff6593aa8376 changeset: 76470:ff6593aa8376 parent: 76468:4a12e8d32ac6 parent: 76469:22f0044ea366 user: Nick Coghlan date: Sun Apr 22 17:16:39 2012 +1000 summary: Resolve #14026 (Merge from 3.2) files: Lib/test/test_cmd_line_script.py | 11 ++++++++--- Misc/NEWS | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -13,6 +13,8 @@ verbose = support.verbose +example_args = ['test1', 'test2', 'test3'] + test_source = """\ # Script may be run with optimisation enabled, so don't rely on assert # statements being executed @@ -36,6 +38,9 @@ # Check the sys module import sys assertIdentical(globals(), sys.modules[__name__].__dict__) +from test import test_cmd_line_script +example_args_list = test_cmd_line_script.example_args +assertEqual(sys.argv[1:], example_args_list) print('sys.argv[0]==%a' % sys.argv[0]) print('sys.path[0]==%a' % sys.path[0]) # Check the working directory @@ -100,7 +105,7 @@ *cmd_line_switches): if not __debug__: cmd_line_switches += ('-' + 'O' * sys.flags.optimize,) - run_args = cmd_line_switches + (script_name,) + run_args = cmd_line_switches + (script_name,) + tuple(example_args) rc, out, err = assert_python_ok(*run_args) self._check_output(script_name, rc, out + err, expected_file, expected_argv0, expected_path0, expected_package) @@ -240,7 +245,7 @@ pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])") script_name = _make_test_script(pkg_dir, 'script') - rc, out, err = assert_python_ok('-m', 'test_pkg.script') + rc, out, err = assert_python_ok('-m', 'test_pkg.script', *example_args) if verbose > 1: print(out) expected = "init_argv0==%r" % '-m' @@ -270,7 +275,7 @@ with support.temp_cwd(path=script_dir): with open("-m", "w") as f: f.write("data") - rc, out, err = assert_python_ok('-m', 'other') + rc, out, err = assert_python_ok('-m', 'other', *example_args) self._check_output(script_name, rc, out, script_name, script_name, '', '') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -146,6 +146,9 @@ Tests ----- +- Issue #14026: In test_cmd_line_script, check that sys.argv is populated + correctly for the various invocation approaches (Patch by Jason Yeo) + - Issue #14032: Fix incorrect variable name in test_cmd_line_script debugging message (Patch by Jason Yeo) -- Repository URL: http://hg.python.org/cpython From ncoghlan at gmail.com Sun Apr 22 09:17:52 2012 From: ncoghlan at gmail.com (Nick Coghlan) Date: Sun, 22 Apr 2012 17:17:52 +1000 Subject: [Python-checkins] cpython: issue2193 - Update docs about the legal characters allowed in Cookie name In-Reply-To: References: Message-ID: On Sun, Apr 22, 2012 at 12:32 PM, senthil.kumaran wrote: > http://hg.python.org/cpython/rev/8cae3ee7f691 > changeset: ? 76465:8cae3ee7f691 > parent: ? ? ?76462:0a63868c5e95 > user: ? ? ? ?Senthil Kumaran > date: ? ? ? ?Sun Apr 22 10:31:52 2012 +0800 > summary: > ?issue2193 - Update docs about the legal characters allowed in Cookie name You missed the dummy merge from 3.2 to indicate that this change had been applied to both branches independently. Should be fixed in my commit for issue #14026 Cheers, Nick. -- Nick Coghlan?? |?? ncoghlan at gmail.com?? |?? Brisbane, Australia From python-checkins at python.org Sun Apr 22 15:56:12 2012 From: python-checkins at python.org (charles-francois.natali) Date: Sun, 22 Apr 2012 15:56:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Use_os=2Epath=2Esamestat=28?= =?utf8?q?=29_instead_of_reinventing_the_wheel=2E?= Message-ID: http://hg.python.org/cpython/rev/b3a565e9701e changeset: 76471:b3a565e9701e user: Charles-Fran?ois Natali date: Sun Apr 22 15:55:43 2012 +0200 summary: Use os.path.samestat() instead of reinventing the wheel. files: Lib/os.py | 11 ++--------- 1 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Lib/os.py b/Lib/os.py --- a/Lib/os.py +++ b/Lib/os.py @@ -126,13 +126,6 @@ umask(mask) return mode & ~mask -def _are_same_file(stat1, stat2): - """Helper function that checks whether two stat results refer to the same - file. - """ - return (stat1.st_ino == stat2.st_ino and stat1.st_dev == stat2.st_dev) -# - # Super directory utilities. # (Inspired by Eric Raymond; the doc strings are mostly his) @@ -345,7 +338,7 @@ topfd = open(top, O_RDONLY) try: if (followlinks or (st.S_ISDIR(orig_st.st_mode) and - _are_same_file(orig_st, fstat(topfd)))): + path.samestat(orig_st, fstat(topfd)))): for x in _fwalk(topfd, top, topdown, onerror, followlinks): yield x finally: @@ -382,7 +375,7 @@ onerror(err) return try: - if followlinks or _are_same_file(orig_st, fstat(dirfd)): + if followlinks or path.samestat(orig_st, fstat(dirfd)): dirpath = path.join(toppath, name) for x in _fwalk(dirfd, dirpath, topdown, onerror, followlinks): yield x -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 19:02:38 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 19:02:38 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Continue_?= =?utf8?q?to_try_to_accomodate_altsep_in_importlib_by_not?= Message-ID: http://hg.python.org/cpython/rev/4e853913054c changeset: 76472:4e853913054c parent: 76468:4a12e8d32ac6 user: Brett Cannon date: Sun Apr 22 11:45:07 2012 -0400 summary: Issue #13959: Continue to try to accomodate altsep in importlib by not ignoring altsep if it already exists on a path when doing a join. files: Lib/importlib/_bootstrap.py | 16 +++++++++++----- Python/importlib.h | Bin 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -61,12 +61,16 @@ return x -# XXX Optimize for single-separator OSs by having two versions of this function -# and choosing in _setup(). -def _path_join(*args): +def _path_join(*path_parts): """Replacement for os.path.join().""" - return path_sep.join(x[:-len(path_sep)] if x.endswith(path_sep) else x - for x in args if x) + new_parts = [] + for part in path_parts: + if not part: + continue + new_parts.append(part) + if part[-1] not in path_separators: + new_parts.append(path_sep) + return ''.join(new_parts[:-1]) # Drop superfluous path separator. def _path_split(path): @@ -1178,6 +1182,8 @@ os_details = ('posix', ['/']), ('nt', ['\\', '/']), ('os2', ['\\', '/']) for builtin_os, path_separators in os_details: + # Assumption made in _path_join() + assert all(len(sep) == 1 for sep in path_separators) path_sep = path_separators[0] if builtin_os in sys.modules: os_module = sys.modules[builtin_os] diff --git a/Python/importlib.h b/Python/importlib.h index c6c561892fde3e990890ac20ea41bc8e63ba372b..4b1001d92beda7856a0d2afd30bbc602a5b4f83f GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 19:02:39 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 19:02:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/9afdbef0622f changeset: 76473:9afdbef0622f parent: 76472:4e853913054c parent: 76471:b3a565e9701e user: Brett Cannon date: Sun Apr 22 13:02:31 2012 -0400 summary: merge files: Lib/os.py | 11 ++--------- Lib/test/test_cmd_line_script.py | 11 ++++++++--- Misc/NEWS | 3 +++ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Lib/os.py b/Lib/os.py --- a/Lib/os.py +++ b/Lib/os.py @@ -126,13 +126,6 @@ umask(mask) return mode & ~mask -def _are_same_file(stat1, stat2): - """Helper function that checks whether two stat results refer to the same - file. - """ - return (stat1.st_ino == stat2.st_ino and stat1.st_dev == stat2.st_dev) -# - # Super directory utilities. # (Inspired by Eric Raymond; the doc strings are mostly his) @@ -345,7 +338,7 @@ topfd = open(top, O_RDONLY) try: if (followlinks or (st.S_ISDIR(orig_st.st_mode) and - _are_same_file(orig_st, fstat(topfd)))): + path.samestat(orig_st, fstat(topfd)))): for x in _fwalk(topfd, top, topdown, onerror, followlinks): yield x finally: @@ -382,7 +375,7 @@ onerror(err) return try: - if followlinks or _are_same_file(orig_st, fstat(dirfd)): + if followlinks or path.samestat(orig_st, fstat(dirfd)): dirpath = path.join(toppath, name) for x in _fwalk(dirfd, dirpath, topdown, onerror, followlinks): yield x diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -13,6 +13,8 @@ verbose = support.verbose +example_args = ['test1', 'test2', 'test3'] + test_source = """\ # Script may be run with optimisation enabled, so don't rely on assert # statements being executed @@ -36,6 +38,9 @@ # Check the sys module import sys assertIdentical(globals(), sys.modules[__name__].__dict__) +from test import test_cmd_line_script +example_args_list = test_cmd_line_script.example_args +assertEqual(sys.argv[1:], example_args_list) print('sys.argv[0]==%a' % sys.argv[0]) print('sys.path[0]==%a' % sys.path[0]) # Check the working directory @@ -100,7 +105,7 @@ *cmd_line_switches): if not __debug__: cmd_line_switches += ('-' + 'O' * sys.flags.optimize,) - run_args = cmd_line_switches + (script_name,) + run_args = cmd_line_switches + (script_name,) + tuple(example_args) rc, out, err = assert_python_ok(*run_args) self._check_output(script_name, rc, out + err, expected_file, expected_argv0, expected_path0, expected_package) @@ -240,7 +245,7 @@ pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])") script_name = _make_test_script(pkg_dir, 'script') - rc, out, err = assert_python_ok('-m', 'test_pkg.script') + rc, out, err = assert_python_ok('-m', 'test_pkg.script', *example_args) if verbose > 1: print(out) expected = "init_argv0==%r" % '-m' @@ -270,7 +275,7 @@ with support.temp_cwd(path=script_dir): with open("-m", "w") as f: f.write("data") - rc, out, err = assert_python_ok('-m', 'other') + rc, out, err = assert_python_ok('-m', 'other', *example_args) self._check_output(script_name, rc, out, script_name, script_name, '', '') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -146,6 +146,9 @@ Tests ----- +- Issue #14026: In test_cmd_line_script, check that sys.argv is populated + correctly for the various invocation approaches (Patch by Jason Yeo) + - Issue #14032: Fix incorrect variable name in test_cmd_line_script debugging message (Patch by Jason Yeo) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 19:16:21 2012 From: python-checkins at python.org (vinay.sajip) Date: Sun, 22 Apr 2012 19:16:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314622=3A_Increased?= =?utf8?q?_default_timeout_for_SMTPHandler=2E?= Message-ID: http://hg.python.org/cpython/rev/fe66fb61f199 changeset: 76474:fe66fb61f199 user: Vinay Sajip date: Sun Apr 22 18:16:14 2012 +0100 summary: Issue #14622: Increased default timeout for SMTPHandler. files: Lib/logging/handlers.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -872,7 +872,7 @@ A handler class which sends an SMTP email for each logging event. """ def __init__(self, mailhost, fromaddr, toaddrs, subject, - credentials=None, secure=None, timeout=1.0): + credentials=None, secure=None, timeout=5.0): """ Initialize the handler. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 19:19:59 2012 From: python-checkins at python.org (vinay.sajip) Date: Sun, 22 Apr 2012 19:19:59 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314644=3A_Increased?= =?utf8?q?_default_timeout_for_SMTPHandler=2E_Note=3A_last_commit?= Message-ID: http://hg.python.org/cpython/rev/bdbcb8f48ddd changeset: 76475:bdbcb8f48ddd user: Vinay Sajip date: Sun Apr 22 18:19:50 2012 +0100 summary: Issue #14644: Increased default timeout for SMTPHandler. Note: last commit message referred to the wrong issue number. files: Lib/test/test_logging.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -930,7 +930,7 @@ sockmap) server.start() addr = ('localhost', server.port) - h = logging.handlers.SMTPHandler(addr, 'me', 'you', 'Log') + h = logging.handlers.SMTPHandler(addr, 'me', 'you', 'Log', timeout=5.0) self.assertEqual(h.toaddrs, ['you']) self.messages = [] r = logging.makeLogRecord({'msg': 'Hello'}) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 19:30:16 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 19:30:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Change_tests_for_imp=2Ecach?= =?utf8?q?e=5Ffrom=5Fsource=28=29_to_follow_os=2Epath=2Ejoin/split?= Message-ID: http://hg.python.org/cpython/rev/2a7f445f71eb changeset: 76476:2a7f445f71eb parent: 76473:9afdbef0622f user: Brett Cannon date: Sun Apr 22 13:29:47 2012 -0400 summary: Change tests for imp.cache_from_source() to follow os.path.join/split semantics. files: Lib/test/test_imp.py | 75 +++++++++++++------------------ 1 files changed, 32 insertions(+), 43 deletions(-) diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -227,73 +227,62 @@ def test_cache_from_source(self): # Given the path to a .py file, return the path to its PEP 3147 # defined .pyc file (i.e. under __pycache__). - self.assertEqual( - imp.cache_from_source('/foo/bar/baz/qux.py', True), - '/foo/bar/baz/__pycache__/qux.{}.pyc'.format(self.tag)) - # Directory with a dot, filename without dot - self.assertEqual( - imp.cache_from_source('/foo.bar/file', True), - '/foo.bar/__pycache__/file{}.pyc'.format(self.tag)) + path = os.path.join('foo', 'bar', 'baz', 'qux.py') + expect = os.path.join('foo', 'bar', 'baz', '__pycache__', + 'qux.{}.pyc'.format(self.tag)) + self.assertEqual(imp.cache_from_source(path, True), expect) + + def test_cache_from_source_no_dot(self): + # Directory with a dot, filename without dot. + path = os.path.join('foo.bar', 'file') + expect = os.path.join('foo.bar', '__pycache__', + 'file{}.pyc'.format(self.tag)) + self.assertEqual(imp.cache_from_source(path, True), expect) def test_cache_from_source_optimized(self): # Given the path to a .py file, return the path to its PEP 3147 # defined .pyo file (i.e. under __pycache__). - self.assertEqual( - imp.cache_from_source('/foo/bar/baz/qux.py', False), - '/foo/bar/baz/__pycache__/qux.{}.pyo'.format(self.tag)) + path = os.path.join('foo', 'bar', 'baz', 'qux.py') + expect = os.path.join('foo', 'bar', 'baz', '__pycache__', + 'qux.{}.pyo'.format(self.tag)) + self.assertEqual(imp.cache_from_source(path, False), expect) def test_cache_from_source_cwd(self): - self.assertEqual(imp.cache_from_source('foo.py', True), - os.sep.join(('__pycache__', - 'foo.{}.pyc'.format(self.tag)))) + path = 'foo.py' + expect = os.path.join('__pycache__', 'foo.{}.pyc'.format(self.tag)) + self.assertEqual(imp.cache_from_source(path, True), expect) def test_cache_from_source_override(self): # When debug_override is not None, it can be any true-ish or false-ish # value. - self.assertEqual( - imp.cache_from_source('/foo/bar/baz.py', []), - '/foo/bar/__pycache__/baz.{}.pyo'.format(self.tag)) - self.assertEqual( - imp.cache_from_source('/foo/bar/baz.py', [17]), - '/foo/bar/__pycache__/baz.{}.pyc'.format(self.tag)) + path = os.path.join('foo', 'bar', 'baz.py') + partial_expect = os.path.join('foo', 'bar', '__pycache__', + 'baz.{}.py'.format(self.tag)) + self.assertEqual(imp.cache_from_source(path, []), partial_expect + 'o') + self.assertEqual(imp.cache_from_source(path, [17]), + partial_expect + 'c') # However if the bool-ishness can't be determined, the exception # propagates. class Bearish: def __bool__(self): raise RuntimeError - self.assertRaises( - RuntimeError, - imp.cache_from_source, '/foo/bar/baz.py', Bearish()) + with self.assertRaises(RuntimeError): + imp.cache_from_source('/foo/bar/baz.py', Bearish()) - @unittest.skipIf(os.altsep is None, - 'test meaningful only where os.altsep is defined') - def test_altsep_cache_from_source(self): - # Windows path and PEP 3147. - self.assertEqual( - imp.cache_from_source('\\foo\\bar\\baz\\qux.py', True), - '\\foo\\bar\\baz\\__pycache__\\qux.{}.pyc'.format(self.tag)) - - @unittest.skipIf(os.altsep is None, - 'test meaningful only where os.altsep is defined') - def test_altsep_and_sep_cache_from_source(self): - # Windows path and PEP 3147 where altsep is right of sep. - self.assertEqual( - imp.cache_from_source('\\foo\\bar/baz\\qux.py', True), - '\\foo\\bar/baz\\__pycache__\\qux.{}.pyc'.format(self.tag)) - - @unittest.skipIf(os.altsep is None, + @unittest.skipUnless(os.sep == '\\' and os.altsep == '/', 'test meaningful only where os.altsep is defined') def test_sep_altsep_and_sep_cache_from_source(self): # Windows path and PEP 3147 where sep is right of altsep. self.assertEqual( imp.cache_from_source('\\foo\\bar\\baz/qux.py', True), - '\\foo\\bar\\baz/__pycache__/qux.{}.pyc'.format(self.tag)) + '\\foo\\bar\\baz\\__pycache__\\qux.{}.pyc'.format(self.tag)) def test_source_from_cache(self): # Given the path to a PEP 3147 defined .pyc file, return the path to # its source. This tests the good path. - self.assertEqual(imp.source_from_cache( - '/foo/bar/baz/__pycache__/qux.{}.pyc'.format(self.tag)), - '/foo/bar/baz/qux.py') + path = os.path.join('foo', 'bar', 'baz', '__pycache__', + 'qux.{}.pyc'.format(self.tag)) + expect = os.path.join('foo', 'bar', 'baz', 'qux.py') + self.assertEqual(imp.source_from_cache(path), expect) def test_source_from_cache_bad_path(self): # When the path to a pyc file is not in PEP 3147 format, a ValueError -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 22 19:30:17 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 22 Apr 2012 19:30:17 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/0a79a2add552 changeset: 76477:0a79a2add552 parent: 76476:2a7f445f71eb parent: 76475:bdbcb8f48ddd user: Brett Cannon date: Sun Apr 22 13:30:07 2012 -0400 summary: merge files: Lib/logging/handlers.py | 2 +- Lib/test/test_logging.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -872,7 +872,7 @@ A handler class which sends an SMTP email for each logging event. """ def __init__(self, mailhost, fromaddr, toaddrs, subject, - credentials=None, secure=None, timeout=1.0): + credentials=None, secure=None, timeout=5.0): """ Initialize the handler. diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -930,7 +930,7 @@ sockmap) server.start() addr = ('localhost', server.port) - h = logging.handlers.SMTPHandler(addr, 'me', 'you', 'Log') + h = logging.handlers.SMTPHandler(addr, 'me', 'you', 'Log', timeout=5.0) self.assertEqual(h.toaddrs, ['you']) self.messages = [] r = logging.makeLogRecord({'msg': 'Hello'}) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 03:43:05 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 23 Apr 2012 03:43:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Expose_im?= =?utf8?q?portlib=2Eabc=2EFileLoader_and?= Message-ID: http://hg.python.org/cpython/rev/1da623513b26 changeset: 76478:1da623513b26 user: Brett Cannon date: Sun Apr 22 19:58:33 2012 -0400 summary: Issue #14605: Expose importlib.abc.FileLoader and importlib.machinery.(FileFinder, SourceFileLoader, _SourcelessFileLoader, ExtensionFileLoader). This exposes all of importlib's mechanisms that will become public on the sys module. files: Doc/library/importlib.rst | 185 ++++++++++ Lib/imp.py | 6 +- Lib/importlib/_bootstrap.py | 101 ++-- Lib/importlib/abc.py | 33 +- Lib/importlib/machinery.py | 4 + Lib/importlib/test/extension/test_case_sensitivity.py | 7 +- Lib/importlib/test/extension/test_finder.py | 7 +- Lib/importlib/test/extension/test_loader.py | 4 +- Lib/importlib/test/extension/test_path_hook.py | 3 +- Lib/importlib/test/source/test_case_sensitivity.py | 11 +- Lib/importlib/test/source/test_file_loader.py | 18 +- Lib/importlib/test/source/test_finder.py | 15 +- Lib/importlib/test/source/test_path_hook.py | 9 +- Lib/importlib/test/source/test_source_encoding.py | 4 +- Lib/importlib/test/test_abc.py | 9 +- Misc/NEWS | 3 + Python/importlib.h | Bin 17 files changed, 328 insertions(+), 91 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -237,6 +237,34 @@ module. +.. class:: FileLoader(fullname, path) + + An abstract base class which inherits from :class:`ResourceLoader` and + :class:`ExecutionLoader`, providing concreate implementations of + :meth:`ResourceLoader.get_data` and :meth:`ExecutionLoader.get_filename`. + + The *fullname* argument is a fully resolved name of the module the loader is + to handle. The *path* argument is the path to the file for the module. + + .. versionadded:: 3.3 + + .. attribute:: name + + The name of the module the loader can handle. + + .. attribute:: path + + Path to the file of the module. + + .. method:: get_filename(fullname) + + Returns :attr:`path`. + + .. method:: get_data(path) + + Returns the open, binary file for *path*. + + .. class:: SourceLoader An abstract base class for implementing source (and optionally bytecode) @@ -498,6 +526,163 @@ module. If no finder is ever found then ``None`` is returned. +.. class:: FileFinder(path, \*loader_details) + + A concrete implementation of :class:`importlib.abc.Finder` which caches + results from the file system. + + The *path* argument is the directory for which the finder is in charge of + searching. + + The *loader_details* argument is a variable number of 3-item tuples each + containing a loader, file suffixes the loader recognizes, and a boolean + representing whether the loader handles packages. + + The finder will cache the directory contents as necessary, making stat calls + for each module search to verify the cache is not outdated. Because cache + staleness relies upon the granularity of the operating system's state + information of the file system, there is a potential race condition of + searching for a module, creating a new file, and then searching for the + module the new file represents. If the operations happen fast enough to fit + within the granularity of stat calls, then the module search will fail. To + prevent this from happening, when you create a module dynamically, make sure + to call :func:`importlib.invalidate_caches`. + + .. versionadded:: 3.3 + + .. attribute:: path + + The path the finder will search in. + + .. method:: find_module(fullname) + + Attempt to find the loader to handle *fullname* within :attr:`path`. + + .. method:: invalidate_caches() + + Clear out the internal cache. + + .. classmethod:: path_hook(\*loader_details) + + A class method which returns a closure for use on :attr:`sys.path_hooks`. + An instance of :class:`FileFinder` is returned by the closure using the + path argument given to the closure directly and *loader_details* + indirectly. + + If the argument to the closure is not an existing directory, + :exc:`ImportError` is raised. + + +.. class:: SourceFileLoader(fullname, path) + + A concrete implementation of :class:`importlib.abc.SourceLoader` by + subclassing :class:`importlib.abc.FileLoader` and providing some concrete + implementations of other methods. + + .. versionadded:: 3.3 + + .. attribute:: name + + The name of the module that this loader will handle. + + .. attribute:: path + + The path to the source file. + + .. method:: is_package(fullname) + + Return true if :attr:`path` appears to be for a package. + + .. method:: path_stats(path) + + Concrete implementation of :meth:`importlib.abc.SourceLoader.path_stats`. + + .. method:: set_data(path, data) + + Concrete implementation of :meth:`importlib.abc.SourceLoader.set_data`. + + .. method:: load_module(fullname) + + Load the specified module if it is the same as :attr:`name`. + + +.. class:: _SourcelessFileLoader(fullname, path) + + A concrete implementation of :class:`importlib.abc.FileLoader` which can + import bytecode files (i.e. no source code files exist). + + It is **strongly** suggested you do not rely on this loader (hence the + leading underscore of the class). Direct use of bytecode files (and thus not + source code files) inhibits your modules from being usable by all Python + implementations. It also runs the risk of your bytecode files not being + usable by new versions of Python which change the bytecode format. This + class is only documented as it is directly used by import and thus can + potentially have instances show up as a module's ``__loader__`` attribute. + + .. versionadded:: 3.3 + + .. attribute:: name + + The name of the module the loader will handle. + + .. attribute:: path + + The path to the bytecode file. + + .. method:: is_package(fullname) + + Determines if the module is a package based on :attr:`path`. + + .. method:: get_code(fullname) + + Returns the code object for :attr:`name` created from :attr:`path`. + + .. method:: get_source(fullname) + + Returns ``None`` as bytecode files have no source when this loader is + used. + + .. method:: load_module(fullname) + + Loads the specified module if it is the same as :attr:`name`. + + +.. class:: ExtensionFileLoader(fullname, path) + + A concrete implementation of :class:`importlib.abc.InspectLoader` for + extension modules. + + The *fullname* argument specifies the name of the module the loader is to + support. The *path* argument is the path to the extension module's file. + + .. versionadded:: 3.3 + + .. attribute:: name + + Name of the module the loader supports. + + .. attribute:: path + + Path to the extension module. + + .. method:: load_module(fullname) + + Loads the extension module if and only if *fullname** is the same as + :attr:`name`. + + .. method:: is_package(fullname) + + Returns ``False`` as extension modules can never be packages. + + .. method:: get_code(fullname) + + Returns ``None`` as extension modules lack a code object. + + .. method:: get_source(fullname) + + Returns ``None`` as extension modules do not have source code. + + :mod:`importlib.util` -- Utility code for importers --------------------------------------------------- diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -71,7 +71,7 @@ def get_data(self, path): """Gross hack to contort loader to deal w/ load_*()'s bad API.""" - if self.file and path == self._path: + if self.file and path == self.path: with self.file: # Technically should be returning bytes, but # SourceLoader.get_code() just passed what is returned to @@ -83,7 +83,7 @@ return super().get_data(path) -class _LoadSourceCompatibility(_HackedGetData, _bootstrap._SourceFileLoader): +class _LoadSourceCompatibility(_HackedGetData, _bootstrap.SourceFileLoader): """Compatibility support for implementing load_source().""" @@ -115,7 +115,7 @@ break else: raise ValueError('{!r} is not a package'.format(path)) - return _bootstrap._SourceFileLoader(name, path).load_module(name) + return _bootstrap.SourceFileLoader(name, path).load_module(name) # XXX deprecate diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -13,6 +13,9 @@ # reference any injected objects! This includes not only global code but also # anything specified at the class level. +# XXX Make sure all public names have no single leading underscore and all +# others do. + # Bootstrap-related code ###################################################### @@ -283,7 +286,7 @@ """ def _check_name_wrapper(self, name, *args, **kwargs): - if self._name != name: + if self.name != name: raise ImportError("loader cannot handle %s" % name, name=name) return method(self, name, *args, **kwargs) _wrap(_check_name_wrapper, method) @@ -423,7 +426,7 @@ class _LoaderBasics: """Base class of common code needed by both SourceLoader and - _SourcelessFileLoader.""" + SourcelessFileLoader.""" def is_package(self, fullname): """Concrete implementation of InspectLoader.is_package by checking if @@ -608,7 +611,7 @@ return self._load_module(fullname) -class _FileLoader: +class FileLoader: """Base file loader class which implements the loader protocol methods that require file system usage.""" @@ -616,13 +619,13 @@ def __init__(self, fullname, path): """Cache the module name and the path to the file found by the finder.""" - self._name = fullname - self._path = path + self.name = fullname + self.path = path @_check_name def get_filename(self, fullname): """Return the path to the source file as found by the finder.""" - return self._path + return self.path def get_data(self, path): """Return the data from path as raw bytes.""" @@ -630,7 +633,7 @@ return file.read() -class _SourceFileLoader(_FileLoader, SourceLoader): +class SourceFileLoader(FileLoader, SourceLoader): """Concrete implementation of SourceLoader using the file system.""" @@ -668,7 +671,7 @@ pass -class _SourcelessFileLoader(_FileLoader, _LoaderBasics): +class _SourcelessFileLoader(FileLoader, _LoaderBasics): """Loader which handles sourceless file imports.""" @@ -692,7 +695,7 @@ return None -class _ExtensionFileLoader: +class ExtensionFileLoader: """Loader for extension modules. @@ -701,8 +704,8 @@ """ def __init__(self, name, path): - self._name = name - self._path = path + self.name = name + self.path = path @_check_name @set_package @@ -711,8 +714,8 @@ """Load an extension module.""" is_reload = fullname in sys.modules try: - module = _imp.load_dynamic(fullname, self._path) - verbose_message('extension module loaded from {!r}', self._path) + module = _imp.load_dynamic(fullname, self.path) + verbose_message('extension module loaded from {!r}', self.path) return module except: if not is_reload and fullname in sys.modules: @@ -805,24 +808,25 @@ return None -class _FileFinder: +class FileFinder: """File-based finder. - Constructor takes a list of objects detailing what file extensions their - loader supports along with whether it can be used for a package. + Interactions with the file system are cached for performance, being + refreshed when the directory the finder is handling has been modified. """ def __init__(self, path, *details): - """Initialize with finder details.""" + """Initialize with the path to search on and a variable number of + 3-tuples containing the loader, file suffixes the loader recognizes, and + a boolean of whether the loader handles packages.""" packages = [] modules = [] - for detail in details: - modules.extend((suffix, detail.loader) for suffix in detail.suffixes) - if detail.supports_packages: - packages.extend((suffix, detail.loader) - for suffix in detail.suffixes) + for loader, suffixes, supports_packages in details: + modules.extend((suffix, loader) for suffix in suffixes) + if supports_packages: + packages.extend((suffix, loader) for suffix in suffixes) self.packages = packages self.modules = modules # Base (directory) path @@ -898,46 +902,29 @@ if sys.platform.startswith(CASE_INSENSITIVE_PLATFORMS): self._relaxed_path_cache = set(fn.lower() for fn in contents) + @classmethod + def path_hook(cls, *loader_details): + """A class method which returns a closure to use on sys.path_hook + which will return an instance using the specified loaders and the path + called on the closure. -class _SourceFinderDetails: + If the path called on the closure is not a directory, ImportError is + raised. - loader = _SourceFileLoader - supports_packages = True + """ + def path_hook_for_FileFinder(path): + """Path hook for importlib.machinery.FileFinder.""" + if not _path_isdir(path): + raise ImportError("only directories are supported", path=path) + return cls(path, *loader_details) - def __init__(self): - self.suffixes = _suffix_list(_imp.PY_SOURCE) + return path_hook_for_FileFinder -class _SourcelessFinderDetails: - - loader = _SourcelessFileLoader - supports_packages = True - - def __init__(self): - self.suffixes = _suffix_list(_imp.PY_COMPILED) - - -class _ExtensionFinderDetails: - - loader = _ExtensionFileLoader - supports_packages = False - - def __init__(self): - self.suffixes = _suffix_list(_imp.C_EXTENSION) # Import itself ############################################################### -def _file_path_hook(path): - """If the path is a directory, return a file-based finder.""" - if _path_isdir(path): - return _FileFinder(path, _ExtensionFinderDetails(), - _SourceFinderDetails(), - _SourcelessFinderDetails()) - else: - raise ImportError("only directories are supported", path=path) - - -_DEFAULT_PATH_HOOK = _file_path_hook +_DEFAULT_PATH_HOOK = None # Set in _setup() class _DefaultPathFinder(PathFinder): @@ -1209,6 +1196,12 @@ if builtin_os == 'nt': SOURCE_SUFFIXES.append('.pyw') + supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), + (SourceFileLoader, _suffix_list(1), True), + (_SourcelessFileLoader, _suffix_list(2), True)] + setattr(self_module, '_DEFAULT_PATH_HOOK', + FileFinder.path_hook(*supported_loaders)) + def _install(sys_module, _imp_module): """Install importlib as the implementation of import. diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -1,6 +1,12 @@ """Abstract base classes related to import.""" from . import _bootstrap from . import machinery +try: + import _frozen_importlib +except ImportError as exc: + if exc.name != '_frozen_importlib': + raise + _frozen_importlib = None import abc import imp import marshal @@ -9,6 +15,14 @@ import warnings +def _register(abstract_cls, *classes): + for cls in classes: + abstract_cls.register(cls) + if _frozen_importlib is not None: + frozen_cls = getattr(_frozen_importlib, cls.__name__) + abstract_cls.register(frozen_cls) + + class Loader(metaclass=abc.ABCMeta): """Abstract base class for import loaders.""" @@ -32,9 +46,8 @@ """ raise NotImplementedError -Finder.register(machinery.BuiltinImporter) -Finder.register(machinery.FrozenImporter) -Finder.register(machinery.PathFinder) +_register(Finder, machinery.BuiltinImporter, machinery.FrozenImporter, + machinery.PathFinder, machinery.FileFinder) class ResourceLoader(Loader): @@ -80,8 +93,8 @@ module. The fullname is a str. Returns a str.""" raise NotImplementedError -InspectLoader.register(machinery.BuiltinImporter) -InspectLoader.register(machinery.FrozenImporter) +_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter, + machinery.ExtensionFileLoader) class ExecutionLoader(InspectLoader): @@ -100,6 +113,15 @@ raise NotImplementedError +class FileLoader(_bootstrap.FileLoader, ResourceLoader, ExecutionLoader): + + """Abstract base class partially implementing the ResourceLoader and + ExecutionLoader ABCs.""" + +_register(FileLoader, machinery.SourceFileLoader, + machinery._SourcelessFileLoader) + + class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader): """Abstract base class for loading source code (and optionally any @@ -146,6 +168,7 @@ """ raise NotImplementedError +_register(SourceLoader, machinery.SourceFileLoader) class PyLoader(SourceLoader): diff --git a/Lib/importlib/machinery.py b/Lib/importlib/machinery.py --- a/Lib/importlib/machinery.py +++ b/Lib/importlib/machinery.py @@ -3,3 +3,7 @@ from ._bootstrap import BuiltinImporter from ._bootstrap import FrozenImporter from ._bootstrap import PathFinder +from ._bootstrap import FileFinder +from ._bootstrap import SourceFileLoader +from ._bootstrap import _SourcelessFileLoader +from ._bootstrap import ExtensionFileLoader diff --git a/Lib/importlib/test/extension/test_case_sensitivity.py b/Lib/importlib/test/extension/test_case_sensitivity.py --- a/Lib/importlib/test/extension/test_case_sensitivity.py +++ b/Lib/importlib/test/extension/test_case_sensitivity.py @@ -1,3 +1,4 @@ +import imp import sys from test import support import unittest @@ -13,8 +14,10 @@ good_name = ext_util.NAME bad_name = good_name.upper() assert good_name != bad_name - finder = _bootstrap._FileFinder(ext_util.PATH, - _bootstrap._ExtensionFinderDetails()) + finder = _bootstrap.FileFinder(ext_util.PATH, + (_bootstrap.ExtensionFileLoader, + _bootstrap._suffix_list(imp.C_EXTENSION), + False)) return finder.find_module(bad_name) def test_case_sensitive(self): diff --git a/Lib/importlib/test/extension/test_finder.py b/Lib/importlib/test/extension/test_finder.py --- a/Lib/importlib/test/extension/test_finder.py +++ b/Lib/importlib/test/extension/test_finder.py @@ -2,6 +2,7 @@ from .. import abc from . import util +import imp import unittest class FinderTests(abc.FinderTests): @@ -9,8 +10,10 @@ """Test the finder for extension modules.""" def find_module(self, fullname): - importer = _bootstrap._FileFinder(util.PATH, - _bootstrap._ExtensionFinderDetails()) + importer = _bootstrap.FileFinder(util.PATH, + (_bootstrap.ExtensionFileLoader, + _bootstrap._suffix_list(imp.C_EXTENSION), + False)) return importer.find_module(fullname) def test_module(self): diff --git a/Lib/importlib/test/extension/test_loader.py b/Lib/importlib/test/extension/test_loader.py --- a/Lib/importlib/test/extension/test_loader.py +++ b/Lib/importlib/test/extension/test_loader.py @@ -12,7 +12,7 @@ """Test load_module() for extension modules.""" def load_module(self, fullname): - loader = _bootstrap._ExtensionFileLoader(ext_util.NAME, + loader = _bootstrap.ExtensionFileLoader(ext_util.NAME, ext_util.FILEPATH) return loader.load_module(fullname) @@ -25,7 +25,7 @@ self.assertEqual(getattr(module, attr), value) self.assertTrue(ext_util.NAME in sys.modules) self.assertTrue(isinstance(module.__loader__, - _bootstrap._ExtensionFileLoader)) + _bootstrap.ExtensionFileLoader)) def test_package(self): # Extensions are not found in packages. diff --git a/Lib/importlib/test/extension/test_path_hook.py b/Lib/importlib/test/extension/test_path_hook.py --- a/Lib/importlib/test/extension/test_path_hook.py +++ b/Lib/importlib/test/extension/test_path_hook.py @@ -14,7 +14,8 @@ # XXX Should it only work for directories containing an extension module? def hook(self, entry): - return _bootstrap._file_path_hook(entry) + return _bootstrap.FileFinder.path_hook((_bootstrap.ExtensionFileLoader, + _bootstrap._suffix_list(imp.C_EXTENSION), False))(entry) def test_success(self): # Path hook should handle a directory where a known extension module diff --git a/Lib/importlib/test/source/test_case_sensitivity.py b/Lib/importlib/test/source/test_case_sensitivity.py --- a/Lib/importlib/test/source/test_case_sensitivity.py +++ b/Lib/importlib/test/source/test_case_sensitivity.py @@ -2,6 +2,7 @@ from importlib import _bootstrap from .. import util from . import util as source_util +import imp import os import sys from test import support as test_support @@ -19,9 +20,13 @@ assert name != name.lower() def find(self, path): - finder = _bootstrap._FileFinder(path, - _bootstrap._SourceFinderDetails(), - _bootstrap._SourcelessFinderDetails()) + finder = _bootstrap.FileFinder(path, + (_bootstrap.SourceFileLoader, + _bootstrap._suffix_list(imp.PY_SOURCE), + True), + (_bootstrap._SourcelessFileLoader, + _bootstrap._suffix_list(imp.PY_COMPILED), + True)) return finder.find_module(self.name) def sensitivity_test(self): diff --git a/Lib/importlib/test/source/test_file_loader.py b/Lib/importlib/test/source/test_file_loader.py --- a/Lib/importlib/test/source/test_file_loader.py +++ b/Lib/importlib/test/source/test_file_loader.py @@ -27,7 +27,7 @@ # [basic] def test_module(self): with source_util.create_modules('_temp') as mapping: - loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) + loader = _bootstrap.SourceFileLoader('_temp', mapping['_temp']) module = loader.load_module('_temp') self.assertTrue('_temp' in sys.modules) check = {'__name__': '_temp', '__file__': mapping['_temp'], @@ -37,7 +37,7 @@ def test_package(self): with source_util.create_modules('_pkg.__init__') as mapping: - loader = _bootstrap._SourceFileLoader('_pkg', + loader = _bootstrap.SourceFileLoader('_pkg', mapping['_pkg.__init__']) module = loader.load_module('_pkg') self.assertTrue('_pkg' in sys.modules) @@ -50,7 +50,7 @@ def test_lacking_parent(self): with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping: - loader = _bootstrap._SourceFileLoader('_pkg.mod', + loader = _bootstrap.SourceFileLoader('_pkg.mod', mapping['_pkg.mod']) module = loader.load_module('_pkg.mod') self.assertTrue('_pkg.mod' in sys.modules) @@ -65,7 +65,7 @@ def test_module_reuse(self): with source_util.create_modules('_temp') as mapping: - loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) + loader = _bootstrap.SourceFileLoader('_temp', mapping['_temp']) module = loader.load_module('_temp') module_id = id(module) module_dict_id = id(module.__dict__) @@ -90,7 +90,7 @@ setattr(orig_module, attr, value) with open(mapping[name], 'w') as file: file.write('+++ bad syntax +++') - loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) + loader = _bootstrap.SourceFileLoader('_temp', mapping['_temp']) with self.assertRaises(SyntaxError): loader.load_module(name) for attr in attributes: @@ -101,7 +101,7 @@ with source_util.create_modules('_temp') as mapping: with open(mapping['_temp'], 'w') as file: file.write('=') - loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) + loader = _bootstrap.SourceFileLoader('_temp', mapping['_temp']) with self.assertRaises(SyntaxError): loader.load_module('_temp') self.assertTrue('_temp' not in sys.modules) @@ -114,7 +114,7 @@ file.write("# test file for importlib") try: with util.uncache('_temp'): - loader = _bootstrap._SourceFileLoader('_temp', file_path) + loader = _bootstrap.SourceFileLoader('_temp', file_path) mod = loader.load_module('_temp') self.assertEqual(file_path, mod.__file__) self.assertEqual(imp.cache_from_source(file_path), @@ -140,7 +140,7 @@ if e.errno != getattr(errno, 'EOVERFLOW', None): raise self.skipTest("cannot set modification time to large integer ({})".format(e)) - loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) + loader = _bootstrap.SourceFileLoader('_temp', mapping['_temp']) mod = loader.load_module('_temp') # Sanity checks. self.assertEqual(mod.__cached__, compiled) @@ -255,7 +255,7 @@ class SourceLoaderBadBytecodeTest(BadBytecodeTest): - loader = _bootstrap._SourceFileLoader + loader = _bootstrap.SourceFileLoader @source_util.writes_bytecode_files def test_empty_file(self): diff --git a/Lib/importlib/test/source/test_finder.py b/Lib/importlib/test/source/test_finder.py --- a/Lib/importlib/test/source/test_finder.py +++ b/Lib/importlib/test/source/test_finder.py @@ -3,6 +3,7 @@ from importlib import _bootstrap import errno +import imp import os import py_compile from test.support import make_legacy_pyc @@ -35,9 +36,11 @@ """ def import_(self, root, module): - finder = _bootstrap._FileFinder(root, - _bootstrap._SourceFinderDetails(), - _bootstrap._SourcelessFinderDetails()) + loader_details = [(_bootstrap.SourceFileLoader, + _bootstrap._suffix_list(imp.PY_SOURCE), True), + (_bootstrap._SourcelessFileLoader, + _bootstrap._suffix_list(imp.PY_COMPILED), True)] + finder = _bootstrap.FileFinder(root, *loader_details) return finder.find_module(module) def run_test(self, test, create=None, *, compile_=None, unlink=None): @@ -135,7 +138,8 @@ def test_empty_string_for_dir(self): # The empty string from sys.path means to search in the cwd. - finder = _bootstrap._FileFinder('', _bootstrap._SourceFinderDetails()) + finder = _bootstrap.FileFinder('', (_bootstrap.SourceFileLoader, + _bootstrap._suffix_list(imp.PY_SOURCE), True)) with open('mod.py', 'w') as file: file.write("# test file for importlib") try: @@ -146,7 +150,8 @@ def test_invalidate_caches(self): # invalidate_caches() should reset the mtime. - finder = _bootstrap._FileFinder('', _bootstrap._SourceFinderDetails()) + finder = _bootstrap.FileFinder('', (_bootstrap.SourceFileLoader, + _bootstrap._suffix_list(imp.PY_SOURCE), True)) finder._path_mtime = 42 finder.invalidate_caches() self.assertEqual(finder._path_mtime, -1) diff --git a/Lib/importlib/test/source/test_path_hook.py b/Lib/importlib/test/source/test_path_hook.py --- a/Lib/importlib/test/source/test_path_hook.py +++ b/Lib/importlib/test/source/test_path_hook.py @@ -1,6 +1,7 @@ from . import util as source_util from importlib import _bootstrap +import imp import unittest @@ -8,14 +9,18 @@ """Test the path hook for source.""" + def path_hook(self): + return _bootstrap.FileFinder.path_hook((_bootstrap.SourceFileLoader, + _bootstrap._suffix_list(imp.PY_SOURCE), True)) + def test_success(self): with source_util.create_modules('dummy') as mapping: - self.assertTrue(hasattr(_bootstrap._file_path_hook(mapping['.root']), + self.assertTrue(hasattr(self.path_hook()(mapping['.root']), 'find_module')) def test_empty_string(self): # The empty string represents the cwd. - self.assertTrue(hasattr(_bootstrap._file_path_hook(''), 'find_module')) + self.assertTrue(hasattr(self.path_hook()(''), 'find_module')) def test_main(): diff --git a/Lib/importlib/test/source/test_source_encoding.py b/Lib/importlib/test/source/test_source_encoding.py --- a/Lib/importlib/test/source/test_source_encoding.py +++ b/Lib/importlib/test/source/test_source_encoding.py @@ -35,7 +35,7 @@ with source_util.create_modules(self.module_name) as mapping: with open(mapping[self.module_name], 'wb') as file: file.write(source) - loader = _bootstrap._SourceFileLoader(self.module_name, + loader = _bootstrap.SourceFileLoader(self.module_name, mapping[self.module_name]) return loader.load_module(self.module_name) @@ -97,7 +97,7 @@ with source_util.create_modules(module_name) as mapping: with open(mapping[module_name], 'wb') as file: file.write(source) - loader = _bootstrap._SourceFileLoader(module_name, + loader = _bootstrap.SourceFileLoader(module_name, mapping[module_name]) return loader.load_module(module_name) diff --git a/Lib/importlib/test/test_abc.py b/Lib/importlib/test/test_abc.py --- a/Lib/importlib/test/test_abc.py +++ b/Lib/importlib/test/test_abc.py @@ -50,7 +50,7 @@ superclasses = [abc.Loader] subclasses = [abc.PyLoader, machinery.BuiltinImporter, - machinery.FrozenImporter] + machinery.FrozenImporter, machinery.ExtensionFileLoader] class ExecutionLoader(InheritanceTests, unittest.TestCase): @@ -59,9 +59,16 @@ subclasses = [abc.PyLoader] +class FileLoader(InheritanceTests, unittest.TestCase): + + superclasses = [abc.ResourceLoader, abc.ExecutionLoader] + subclasses = [machinery.SourceFileLoader, machinery._SourcelessFileLoader] + + class SourceLoader(InheritanceTests, unittest.TestCase): superclasses = [abc.ResourceLoader, abc.ExecutionLoader] + subclasses = [machinery.SourceFileLoader] class PyLoader(InheritanceTests, unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,9 @@ Library ------- +- Issue #14605: Add importlib.abc.FileLoader, importlib.machinery.(FileFinder, + SourceFileLoader, _SourcelessFileLoader, ExtensionFileLoader). + - Issue #13959: imp.cache_from_source()/source_from_cache() now follow os.path.join()/split() semantics for path manipulation instead of its prior, custom semantics of caring the right-most path separator forward in path diff --git a/Python/importlib.h b/Python/importlib.h index 4b1001d92beda7856a0d2afd30bbc602a5b4f83f..bc4c0d9638e4f8f252a80b871ad40a9fa85bf97e GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Apr 23 05:34:08 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 23 Apr 2012 05:34:08 +0200 Subject: [Python-checkins] Daily reference leaks (0a79a2add552): sum=2 Message-ID: results for 0a79a2add552 on branch "default" -------------------------------------------- test_dbm leaked [0, 0, 2] references, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogwHFSfL', '-x'] From python-checkins at python.org Mon Apr 23 06:32:45 2012 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Apr 2012 06:32:45 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Restore_the_prohibition_agains?= =?utf8?q?t_using_function_annotations_in_the_standard?= Message-ID: http://hg.python.org/peps/rev/baf779fbc6e7 changeset: 4294:baf779fbc6e7 user: Raymond Hettinger date: Sun Apr 22 21:32:34 2012 -0700 summary: Restore the prohibition against using function annotations in the standard library. At Guido's request, added notes regarding issues observed with various developer's early attempts to use function annotations. files: pep-0008.txt | 53 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 52 insertions(+), 1 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -140,7 +140,7 @@ is *after* the operator, not before it. Some examples:: class Rectangle(Blob): - + def __init__(self, width, height, color='black', emphasis=None, highlight=0): if (width == 0 and height == 0 and @@ -887,6 +887,57 @@ No: if greeting == True: Worse: if greeting is True: +- The Python standard library will not use function annotations as + that would result in a premature commitment to a particular + annotation style. Instead, the annotations are left for users to + discover and experiment with useful annotation styles. + + Early core developer attempts to use function annotations revealed + inconsistent, ad-hoc annotation styles. For example: + + * ``[str]`` was ambiguous as to whether it represented a list of + strings or a value that could be either *str* or *None*. + + * The notation ``open(file:(str,bytes))`` was used for a value that + could be either *bytes* or *str* rather than a 2-tuple containing + a *str* value followed by a *bytes* value. + + * The annotation ``seek(whence:int)`` exhibited an mix of + over-specification and under-specification: *int* is too + restrictive (anything with ``__index__`` would be allowed) and it + is not restrictive enough (only the values 0, 1, and 2 are + allowed). Likewise, the annotation ``write(b: bytes)`` was also + too restrictive (anything supporting the buffer protocol would be + allowed). + + * Annotations such as ``read1(n: int=None)`` were self-contradictory + since *None* is not an *int*. Annotations such as + ``source_path(self, fullname:str) -> object`` were confusing about + what the return type should be. + + * In addition to the above, annotations were inconsistent in the use + of concrete types versus abstract types: *int* versus *Integral* + and set/frozenset versus MutableSet/Set. + + * Some annotations in the abstract base classes were incorrect + specifications. For example, set-to-set operations require + *other* to be another instance of *Set* rather than just an + *Iterable*. + + * A further issue was that annotations become part of the + specification but weren't being tested. + + * In most cases, the docstrings already included the type + specifications and did so with greater clarity than the function + annotations. In the remaining cases, the docstrings were improved + once the annotations were removed. + + * The observed function annotations were too ad-hoc and inconsistent + to work with a coherent system of automatic type checking or + argument validation. Leaving these annotations in the code would + have made it more difficult to make changes later so that + automated utilities could be supported. + References ========== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 23 09:22:57 2012 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Apr 2012 09:22:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Minor_fixups=2E?= Message-ID: http://hg.python.org/cpython/rev/90aa4daf42d3 changeset: 76479:90aa4daf42d3 branch: 2.7 parent: 76387:d229032dc213 user: Raymond Hettinger date: Wed Apr 18 00:25:32 2012 -0400 summary: Minor fixups. files: Doc/library/sqlite3.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -15,12 +15,12 @@ application using SQLite and then port the code to a larger database such as PostgreSQL or Oracle. -sqlite3 was written by Gerhard H?ring and provides a SQL interface compliant -with the DB-API 2.0 specification described by :pep:`249`. +The sqlite3 module was written by Gerhard H?ring. It provides a SQL interface +compliant with the DB-API 2.0 specification described by :pep:`249`. To use the module, you must first create a :class:`Connection` object that represents the database. Here the data will be stored in the -:file:`/tmp/example` file:: +:file:`example.db` file:: import sqlite3 conn = sqlite3.connect('example.db') @@ -473,7 +473,7 @@ .. method:: Cursor.execute(sql, [parameters]) - Executes an SQL statement. The SQL statement may be parametrized (i. e. + Executes an SQL statement. The SQL statement may be parameterized (i. e. placeholders instead of SQL literals). The :mod:`sqlite3` module supports two kinds of placeholders: question marks (qmark style) and named placeholders (named style). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 09:22:58 2012 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Apr 2012 09:22:58 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_merge?= Message-ID: http://hg.python.org/cpython/rev/db26c4daecbb changeset: 76480:db26c4daecbb branch: 2.7 parent: 76479:90aa4daf42d3 parent: 76463:a8af49baa636 user: Raymond Hettinger date: Mon Apr 23 00:22:48 2012 -0700 summary: merge files: Doc/library/cookie.rst | 10 ++++++- Doc/library/webbrowser.rst | 9 +----- Lib/HTMLParser.py | 6 ++-- Lib/test/test_htmlparser.py | 10 +++++++ Lib/test/test_sys_settrace.py | 11 ++++++++ Lib/test/test_threading.py | 29 +++++++++++++++++++++++ Lib/threading.py | 4 +++ Misc/NEWS | 8 ++++++ Objects/frameobject.c | 6 +++- Python/import.c | 3 +- 10 files changed, 81 insertions(+), 15 deletions(-) diff --git a/Doc/library/cookie.rst b/Doc/library/cookie.rst --- a/Doc/library/cookie.rst +++ b/Doc/library/cookie.rst @@ -22,8 +22,14 @@ The module formerly strictly applied the parsing rules described in the :rfc:`2109` and :rfc:`2068` specifications. It has since been discovered that -MSIE 3.0x doesn't follow the character rules outlined in those specs. As a -result, the parsing rules used are a bit less strict. +MSIE 3.0x doesn't follow the character rules outlined in those specs and also +many current day browsers and servers have relaxed parsing rules when comes to +Cookie handling. As a result, the parsing rules used are a bit less strict. + +The character set, :data:`string.ascii_letters`, :data:`string.digits` and +``!#$%&'*+-.^_`|~`` denote the set of valid characters allowed by this module +in Cookie name (as :attr:`~Morsel.key`). + .. note:: diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -138,11 +138,9 @@ +-----------------------+-----------------------------------------+-------+ | ``'windows-default'`` | :class:`WindowsDefault` | \(2) | +-----------------------+-----------------------------------------+-------+ -| ``'internet-config'`` | :class:`InternetConfig` | \(3) | +| ``'macosx'`` | :class:`MacOSX('default')` | \(3) | +-----------------------+-----------------------------------------+-------+ -| ``'macosx'`` | :class:`MacOSX('default')` | \(4) | -+-----------------------+-----------------------------------------+-------+ -| ``'safari'`` | :class:`MacOSX('safari')` | \(4) | +| ``'safari'`` | :class:`MacOSX('safari')` | \(3) | +-----------------------+-----------------------------------------+-------+ Notes: @@ -158,9 +156,6 @@ Only on Windows platforms. (3) - Only on Mac OS platforms; requires the standard MacPython :mod:`ic` module. - -(4) Only on Mac OS X platform. Here are some simple examples:: diff --git a/Lib/HTMLParser.py b/Lib/HTMLParser.py --- a/Lib/HTMLParser.py +++ b/Lib/HTMLParser.py @@ -22,13 +22,13 @@ starttagopen = re.compile('<[a-zA-Z]') piclose = re.compile('>') commentclose = re.compile(r'--\s*>') -tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*') +tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*') # see http://www.w3.org/TR/html5/tokenization.html#tag-open-state # and http://www.w3.org/TR/html5/tokenization.html#tag-name-state tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*') attrfind = re.compile( - r'[\s/]*((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' + r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*') locatestarttagend = re.compile(r""" @@ -289,7 +289,7 @@ match = tagfind.match(rawdata, i+1) assert match, 'unexpected call to parse_starttag()' k = match.end() - self.lasttag = tag = rawdata[i+1:k].lower() + self.lasttag = tag = match.group(1).lower() while k < endpos: m = attrfind.match(rawdata, k) diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -260,6 +260,16 @@ ('starttag', 'a', [('foo', None), ('=', None), ('bar', None)]) ] self._run_check(html, expected) + #see issue #14538 + html = ('' + '') + expected = [ + ('starttag', 'meta', []), ('starttag', 'meta', []), + ('starttag', 'meta', []), ('starttag', 'meta', []), + ('startendtag', 'meta', []), ('startendtag', 'meta', []), + ('startendtag', 'meta', []), ('startendtag', 'meta', []), + ] + self._run_check(html, expected) def test_declaration_junk_chars(self): self._run_check("", [('decl', 'DOCTYPE foo $ ')]) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -670,6 +670,14 @@ no_jump_to_non_integers.jump = (2, "Spam") no_jump_to_non_integers.output = [True] +def jump_across_with(output): + with open(test_support.TESTFN, "wb") as fp: + pass + with open(test_support.TESTFN, "wb") as fp: + pass +jump_across_with.jump = (1, 3) +jump_across_with.output = [] + # This verifies that you can't set f_lineno via _getframe or similar # trickery. def no_jump_without_trace_function(): @@ -739,6 +747,9 @@ self.run_test(no_jump_to_non_integers) def test_19_no_jump_without_trace_function(self): no_jump_without_trace_function() + def test_jump_across_with(self): + self.addCleanup(test_support.unlink, test_support.TESTFN) + self.run_test(jump_across_with) def test_20_large_function(self): d = {} diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -2,6 +2,8 @@ import test.test_support from test.test_support import verbose +from test.script_helper import assert_python_ok + import random import re import sys @@ -414,6 +416,33 @@ msg=('%d references still around' % sys.getrefcount(weak_raising_cyclic_object()))) + @unittest.skipUnless(hasattr(os, 'fork'), 'test needs fork()') + def test_dummy_thread_after_fork(self): + # Issue #14308: a dummy thread in the active list doesn't mess up + # the after-fork mechanism. + code = """if 1: + import thread, threading, os, time + + def background_thread(evt): + # Creates and registers the _DummyThread instance + threading.current_thread() + evt.set() + time.sleep(10) + + evt = threading.Event() + thread.start_new_thread(background_thread, (evt,)) + evt.wait() + assert threading.active_count() == 2, threading.active_count() + if os.fork() == 0: + assert threading.active_count() == 1, threading.active_count() + os._exit(0) + else: + os.wait() + """ + _, out, err = assert_python_ok("-c", code) + self.assertEqual(out, '') + self.assertEqual(err, '') + class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -605,6 +605,10 @@ pass def __stop(self): + # DummyThreads delete self.__block, but they have no waiters to + # notify anyway (join() is forbidden on them). + if not hasattr(self, '_Thread__block'): + return self.__block.acquire() self.__stopped = True self.__block.notify_all() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,8 @@ Core and Builtins ----------------- +- Issue #14612: Fix jumping around with blocks by setting f_lineno. + - Issue #13889: Check and (if necessary) set FPU control word before calling any of the dtoa.c string <-> float conversion functions, on MSVC builds of Python. This fixes issues when embedding Python in a Delphi app. @@ -48,6 +50,12 @@ Library ------- +- Issue #14308: Fix an exception when a "dummy" thread is in the threading + module's active list after a fork(). + +- Issue #14538: HTMLParser can now parse correctly start tags that contain + a bare '/'. + - Issue #14452: SysLogHandler no longer inserts a UTF-8 BOM into the message. - Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied diff --git a/Objects/frameobject.c b/Objects/frameobject.c --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -214,6 +214,7 @@ case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: blockstack[blockstack_top++] = addr; in_finally[blockstack_top-1] = 0; break; @@ -221,7 +222,7 @@ case POP_BLOCK: assert(blockstack_top > 0); setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { in_finally[blockstack_top-1] = 1; } else { @@ -236,7 +237,7 @@ * be seeing such an END_FINALLY.) */ if (blockstack_top > 0) { setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { blockstack_top--; } } @@ -298,6 +299,7 @@ case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: delta_iblock++; break; diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1267,7 +1267,8 @@ } name = PyMem_MALLOC(MAXPATHLEN+1); if (name == NULL) { - return PyErr_NoMemory(); + PyErr_NoMemory(); + return NULL; } strcpy(name, subname); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 16:08:59 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 16:08:59 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_sleep_here?= Message-ID: http://hg.python.org/cpython/rev/1040e3811485 changeset: 76481:1040e3811485 branch: 3.2 parent: 76469:22f0044ea366 user: Benjamin Peterson date: Mon Apr 23 10:08:14 2012 -0400 summary: sleep here files: Lib/test/test_thread.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -148,7 +148,7 @@ thread.start_new_thread(task, ()) started.acquire() while thread._count() > c: - pass + time.sleep(0.01) self.assertIn("Traceback", stderr.getvalue()) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 16:09:00 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 16:09:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/b1bd900cc723 changeset: 76482:b1bd900cc723 parent: 76478:1da623513b26 parent: 76481:1040e3811485 user: Benjamin Peterson date: Mon Apr 23 10:08:20 2012 -0400 summary: merge 3.2 files: Lib/test/test_thread.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -148,7 +148,7 @@ thread.start_new_thread(task, ()) started.acquire() while thread._count() > c: - pass + time.sleep(0.01) self.assertIn("Traceback", stderr.getvalue()) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 16:09:01 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 16:09:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_sleep_here?= Message-ID: http://hg.python.org/cpython/rev/3182453e74f9 changeset: 76483:3182453e74f9 branch: 2.7 parent: 76480:db26c4daecbb user: Benjamin Peterson date: Mon Apr 23 10:08:14 2012 -0400 summary: sleep here files: Lib/test/test_thread.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -150,7 +150,7 @@ thread.start_new_thread(task, ()) started.acquire() while thread._count() > c: - pass + time.sleep(0.01) self.assertIn("Traceback", stderr.getvalue()) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 16:55:36 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 16:55:36 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_inherit_maxchar_of_field_va?= =?utf8?q?lue_where_needed_=28closes_=2314648=29?= Message-ID: http://hg.python.org/cpython/rev/c7163a7f7cd2 changeset: 76484:c7163a7f7cd2 parent: 76482:b1bd900cc723 user: Benjamin Peterson date: Mon Apr 23 10:55:29 2012 -0400 summary: inherit maxchar of field value where needed (closes #14648) files: Lib/test/test_unicode.py | 2 ++ Python/formatter_unicode.c | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -1056,6 +1056,8 @@ self.assertEqual('%f' % INF, 'inf') self.assertEqual('%F' % INF, 'INF') + self.assertEqual(format("\u0410\u0411\u0412", "s"), "???") + def test_startswith_endswith_errors(self): for meth in ('foo'.startswith, 'foo'.endswith): with self.assertRaises(TypeError) as cm: diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -747,6 +747,9 @@ len = format->precision; } + if (len) + maxchar = PyUnicode_MAX_CHAR_VALUE(value); + calc_padding(len, format->width, format->align, &lpad, &rpad, &total); if (lpad != 0 || rpad != 0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:24:57 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 17:24:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Implement_PEP_412=3A_Key-sh?= =?utf8?q?aring_dictionaries_=28closes_=2313903=29?= Message-ID: http://hg.python.org/cpython/rev/6e5855854a2e changeset: 76485:6e5855854a2e user: Benjamin Peterson date: Mon Apr 23 11:24:50 2012 -0400 summary: Implement PEP 412: Key-sharing dictionaries (closes #13903) Patch from Mark Shannon. files: Include/dictobject.h | 88 +- Include/object.h | 2 +- Lib/test/test_dict.py | 21 + Lib/test/test_pprint.py | 4 + Lib/test/test_sys.py | 6 +- Misc/NEWS | 4 + Objects/dictnotes.txt | 221 +-- Objects/dictobject.c | 1783 ++++++++++++++++++-------- Objects/object.c | 27 +- Objects/typeobject.c | 17 +- Python/ceval.c | 75 +- Tools/gdb/libpython.py | 11 +- 12 files changed, 1357 insertions(+), 902 deletions(-) diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -13,78 +13,20 @@ tuning dictionaries, and several ideas for possible optimizations. */ -/* -There are three kinds of slots in the table: +#ifndef Py_LIMITED_API -1. Unused. me_key == me_value == NULL - Does not hold an active (key, value) pair now and never did. Unused can - transition to Active upon key insertion. This is the only case in which - me_key is NULL, and is each slot's initial state. +typedef struct _dictkeysobject PyDictKeysObject; -2. Active. me_key != NULL and me_key != dummy and me_value != NULL - Holds an active (key, value) pair. Active can transition to Dummy upon - key deletion. This is the only case in which me_value != NULL. +/* The ma_values pointer is NULL for a combined table + * or points to an array of PyObject* for a split table + */ +typedef struct { + PyObject_HEAD + Py_ssize_t ma_used; + PyDictKeysObject *ma_keys; + PyObject **ma_values; +} PyDictObject; -3. Dummy. me_key == dummy and me_value == NULL - Previously held an active (key, value) pair, but that was deleted and an - active pair has not yet overwritten the slot. Dummy can transition to - Active upon key insertion. Dummy slots cannot be made Unused again - (cannot have me_key set to NULL), else the probe sequence in case of - collision would have no way to know they were once active. - -Note: .popitem() abuses the me_hash field of an Unused or Dummy slot to -hold a search finger. The me_hash field of Unused or Dummy slots has no -meaning otherwise. -*/ - -/* PyDict_MINSIZE is the minimum size of a dictionary. This many slots are - * allocated directly in the dict object (in the ma_smalltable member). - * It must be a power of 2, and at least 4. 8 allows dicts with no more - * than 5 active entries to live in ma_smalltable (and so avoid an - * additional malloc); instrumentation suggested this suffices for the - * majority of dicts (consisting mostly of usually-small instance dicts and - * usually-small dicts created to pass keyword arguments). - */ -#ifndef Py_LIMITED_API -#define PyDict_MINSIZE 8 - -typedef struct { - /* Cached hash code of me_key. */ - Py_hash_t me_hash; - PyObject *me_key; - PyObject *me_value; -} PyDictEntry; - -/* -To ensure the lookup algorithm terminates, there must be at least one Unused -slot (NULL key) in the table. -The value ma_fill is the number of non-NULL keys (sum of Active and Dummy); -ma_used is the number of non-NULL, non-dummy keys (== the number of non-NULL -values == the number of Active items). -To avoid slowing down lookups on a near-full table, we resize the table when -it's two-thirds full. -*/ -typedef struct _dictobject PyDictObject; -struct _dictobject { - PyObject_HEAD - Py_ssize_t ma_fill; /* # Active + # Dummy */ - Py_ssize_t ma_used; /* # Active */ - - /* The table contains ma_mask + 1 slots, and that's a power of 2. - * We store the mask instead of the size because the mask is more - * frequently needed. - */ - Py_ssize_t ma_mask; - - /* ma_table points to ma_smalltable for small tables, else to - * additional malloc'ed memory. ma_table is never NULL! This rule - * saves repeated runtime null-tests in the workhorse getitem and - * setitem calls. - */ - PyDictEntry *ma_table; - PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, Py_hash_t hash); - PyDictEntry ma_smalltable[PyDict_MINSIZE]; -}; #endif /* Py_LIMITED_API */ PyAPI_DATA(PyTypeObject) PyDict_Type; @@ -117,6 +59,8 @@ PyAPI_FUNC(int) PyDict_Next( PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value); #ifndef Py_LIMITED_API +PyDictKeysObject *_PyDict_NewKeysForClass(void); +PyAPI_FUNC(PyObject *) PyObject_GenericGetDict(PyObject *, void *); PyAPI_FUNC(int) _PyDict_Next( PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); #endif @@ -131,6 +75,7 @@ PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); +#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) PyAPI_FUNC(int) PyDict_ClearFreeList(void); #endif @@ -162,6 +107,11 @@ PyAPI_FUNC(int) _PyDict_SetItemId(PyObject *dp, struct _Py_Identifier *key, PyObject *item); PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key); +#ifndef Py_LIMITED_API +int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value); +PyObject *_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); +#endif + #ifdef __cplusplus } #endif diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -449,6 +449,7 @@ see add_operators() in typeobject.c . */ PyBufferProcs as_buffer; PyObject *ht_name, *ht_slots, *ht_qualname; + struct _dictkeysobject *ht_cached_keys; /* here are optional user slots, followed by the members. */ } PyHeapTypeObject; @@ -517,7 +518,6 @@ PyAPI_FUNC(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *); PyAPI_FUNC(int) PyObject_GenericSetAttr(PyObject *, PyObject *, PyObject *); -PyAPI_FUNC(PyObject *) PyObject_GenericGetDict(PyObject *, void *); PyAPI_FUNC(int) PyObject_GenericSetDict(PyObject *, PyObject *, void *); PyAPI_FUNC(Py_hash_t) PyObject_Hash(PyObject *); PyAPI_FUNC(Py_hash_t) PyObject_HashNotImplemented(PyObject *); diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -321,6 +321,27 @@ self.assertEqual(hashed2.hash_count, 1) self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1) + def test_setitem_atomic_at_resize(self): + class Hashed(object): + def __init__(self): + self.hash_count = 0 + self.eq_count = 0 + def __hash__(self): + self.hash_count += 1 + return 42 + def __eq__(self, other): + self.eq_count += 1 + return id(self) == id(other) + hashed1 = Hashed() + # 5 items + y = {hashed1: 5, 0: 0, 1: 1, 2: 2, 3: 3} + hashed2 = Hashed() + # 6th item forces a resize + y[hashed2] = [] + self.assertEqual(hashed1.hash_count, 1) + self.assertEqual(hashed2.hash_count, 1) + self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1) + def test_popitem(self): # dict.popitem() for copymode in -1, +1: diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -219,6 +219,8 @@ others.should.not.be: like.this}""" self.assertEqual(DottedPrettyPrinter().pformat(o), exp) + @unittest.expectedFailure + #See http://bugs.python.org/issue13907 @test.support.cpython_only def test_set_reprs(self): # This test creates a complex arrangement of frozensets and @@ -241,10 +243,12 @@ # Consequently, this test is fragile and # implementation-dependent. Small changes to Python's sort # algorithm cause the test to fail when it should pass. + # XXX Or changes to the dictionary implmentation... self.assertEqual(pprint.pformat(set()), 'set()') self.assertEqual(pprint.pformat(set(range(3))), '{0, 1, 2}') self.assertEqual(pprint.pformat(frozenset()), 'frozenset()') + self.assertEqual(pprint.pformat(frozenset(range(3))), 'frozenset({0, 1, 2})') cube_repr_tgt = """\ {frozenset(): frozenset({frozenset({2}), frozenset({0}), frozenset({1})}), diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -687,9 +687,9 @@ # method-wrapper (descriptor object) check({}.__iter__, size(h + '2P')) # dict - check({}, size(h + '3P2P' + 8*'P2P')) + check({}, size(h + '3P' + '4P' + 8*'P2P')) longdict = {1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8} - check(longdict, size(h + '3P2P' + 8*'P2P') + 16*size('P2P')) + check(longdict, size(h + '3P' + '4P') + 16*size('P2P')) # dictionary-keyiterator check({}.keys(), size(h + 'P')) # dictionary-valueiterator @@ -831,7 +831,7 @@ # type # (PyTypeObject + PyNumberMethods + PyMappingMethods + # PySequenceMethods + PyBufferProcs) - s = size(vh + 'P2P15Pl4PP9PP11PI') + size('16Pi17P 3P 10P 2P 3P') + s = size(vh + 'P2P15Pl4PP9PP11PIP') + size('16Pi17P 3P 10P 2P 3P') check(int, s) # class class newstyleclass(object): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #13903: Implement PEP 412. Individual dictionary instances can now share + their keys with other dictionaries. Classes take advantage of this to share + their instance dictionary keys for improved memory and performance. + - Issue #14630: Fix a memory access bug for instances of a subclass of int with value 0. diff --git a/Objects/dictnotes.txt b/Objects/dictnotes.txt --- a/Objects/dictnotes.txt +++ b/Objects/dictnotes.txt @@ -1,7 +1,6 @@ -NOTES ON OPTIMIZING DICTIONARIES +NOTES ON DICTIONARIES ================================ - Principal Use Cases for Dictionaries ------------------------------------ @@ -21,7 +20,7 @@ Builtins Frequent reads. Almost never written. - Size 126 interned strings (as of Py2.3b1). + About 150 interned strings (as of Py3.3). A few keys are accessed much more frequently than others. Uniquification @@ -59,44 +58,43 @@ Characterized by deletions interspersed with adds and replacements. Performance benefits greatly from the re-use of dummy entries. +Data Layout +----------- -Data Layout (assuming a 32-bit box with 64 bytes per cache line) ----------------------------------------------------------------- - -Smalldicts (8 entries) are attached to the dictobject structure -and the whole group nearly fills two consecutive cache lines. - -Larger dicts use the first half of the dictobject structure (one cache -line) and a separate, continuous block of entries (at 12 bytes each -for a total of 5.333 entries per cache line). +Dictionaries are composed of 3 components: +The dictobject struct itself +A dict-keys object (keys & hashes) +A values array Tunable Dictionary Parameters ----------------------------- -* PyDict_MINSIZE. Currently set to 8. - Must be a power of two. New dicts have to zero-out every cell. - Each additional 8 consumes 1.5 cache lines. Increasing improves - the sparseness of small dictionaries but costs time to read in - the additional cache lines if they are not already in cache. - That case is common when keyword arguments are passed. +* PyDict_STARTSIZE. Starting size of dict (unless an instance dict). + Currently set to 8. Must be a power of two. + New dicts have to zero-out every cell. + Increasing improves the sparseness of small dictionaries but costs + time to read in the additional cache lines if they are not already + in cache. That case is common when keyword arguments are passed. + Prior to version 3.3, PyDict_MINSIZE was used as the starting size + of a new dict. -* Maximum dictionary load in PyDict_SetItem. Currently set to 2/3. - Increasing this ratio makes dictionaries more dense resulting - in more collisions. Decreasing it improves sparseness at the - expense of spreading entries over more cache lines and at the +* PyDict_MINSIZE. Minimum size of a dict. + Currently set to 4 (to keep instance dicts small). + Must be a power of two. Prior to version 3.3, PyDict_MINSIZE was + set to 8. + +* USABLE_FRACTION. Maximum dictionary load in PyDict_SetItem. + Currently set to 2/3. Increasing this ratio makes dictionaries more + dense resulting in more collisions. Decreasing it improves sparseness + at the expense of spreading entries over more cache lines and at the cost of total memory consumed. - The load test occurs in highly time sensitive code. Efforts - to make the test more complex (for example, varying the load - for different sizes) have degraded performance. - * Growth rate upon hitting maximum load. Currently set to *2. - Raising this to *4 results in half the number of resizes, - less effort to resize, better sparseness for some (but not - all dict sizes), and potentially doubles memory consumption - depending on the size of the dictionary. Setting to *4 - eliminates every other resize step. + Raising this to *4 results in half the number of resizes, less + effort to resize, better sparseness for some (but not all dict sizes), + and potentially doubles memory consumption depending on the size of + the dictionary. Setting to *4 eliminates every other resize step. * Maximum sparseness (minimum dictionary load). What percentage of entries can be unused before the dictionary shrinks to @@ -126,8 +124,8 @@ Also, every dictionary iterates at least twice, once for the memset() when it is created and once by dealloc(). -Dictionary operations involving only a single key can be O(1) unless -resizing is possible. By checking for a resize only when the +Dictionary operations involving only a single key can be O(1) unless +resizing is possible. By checking for a resize only when the dictionary can grow (and may *require* resizing), other operations remain O(1), and the odds of resize thrashing or memory fragmentation are reduced. In particular, an algorithm that empties a dictionary @@ -135,136 +133,51 @@ not be necessary at all because the dictionary is eventually discarded entirely. +The key differences between this implementation and earlier versions are: + 1. The table can be split into two parts, the keys and the values. + + 2. There is an additional key-value combination: (key, NULL). + Unlike (, NULL) which represents a deleted value, (key, NULL) + represented a yet to be inserted value. This combination can only occur + when the table is split. + + 3. No small table embedded in the dict, + as this would make sharing of key-tables impossible. + + +These changes have the following consequences. + 1. General dictionaries are slightly larger. + + 2. All object dictionaries of a single class can share a single key-table, + saving about 60% memory for such cases. Results of Cache Locality Experiments -------------------------------------- +-------------------------------------- -When an entry is retrieved from memory, 4.333 adjacent entries are also -retrieved into a cache line. Since accessing items in cache is *much* -cheaper than a cache miss, an enticing idea is to probe the adjacent -entries as a first step in collision resolution. Unfortunately, the -introduction of any regularity into collision searches results in more -collisions than the current random chaining approach. +Experiments on an earlier design of dictionary, in which all tables were +combined, showed the following: -Exploiting cache locality at the expense of additional collisions fails -to payoff when the entries are already loaded in cache (the expense -is paid with no compensating benefit). This occurs in small dictionaries -where the whole dictionary fits into a pair of cache lines. It also -occurs frequently in large dictionaries which have a common access pattern -where some keys are accessed much more frequently than others. The -more popular entries *and* their collision chains tend to remain in cache. + When an entry is retrieved from memory, several adjacent entries are also + retrieved into a cache line. Since accessing items in cache is *much* + cheaper than a cache miss, an enticing idea is to probe the adjacent + entries as a first step in collision resolution. Unfortunately, the + introduction of any regularity into collision searches results in more + collisions than the current random chaining approach. -To exploit cache locality, change the collision resolution section -in lookdict() and lookdict_string(). Set i^=1 at the top of the -loop and move the i = (i << 2) + i + perturb + 1 to an unrolled -version of the loop. + Exploiting cache locality at the expense of additional collisions fails + to payoff when the entries are already loaded in cache (the expense + is paid with no compensating benefit). This occurs in small dictionaries + where the whole dictionary fits into a pair of cache lines. It also + occurs frequently in large dictionaries which have a common access pattern + where some keys are accessed much more frequently than others. The + more popular entries *and* their collision chains tend to remain in cache. -This optimization strategy can be leveraged in several ways: + To exploit cache locality, change the collision resolution section + in lookdict() and lookdict_string(). Set i^=1 at the top of the + loop and move the i = (i << 2) + i + perturb + 1 to an unrolled + version of the loop. -* If the dictionary is kept sparse (through the tunable parameters), -then the occurrence of additional collisions is lessened. +For split tables, the above will apply to the keys, but the value will +always be in a different cache line from the key. -* If lookdict() and lookdict_string() are specialized for small dicts -and for largedicts, then the versions for large_dicts can be given -an alternate search strategy without increasing collisions in small dicts -which already have the maximum benefit of cache locality. -* If the use case for a dictionary is known to have a random key -access pattern (as opposed to a more common pattern with a Zipf's law -distribution), then there will be more benefit for large dictionaries -because any given key is no more likely than another to already be -in cache. - -* In use cases with paired accesses to the same key, the second access -is always in cache and gets no benefit from efforts to further improve -cache locality. - -Optimizing the Search of Small Dictionaries -------------------------------------------- - -If lookdict() and lookdict_string() are specialized for smaller dictionaries, -then a custom search approach can be implemented that exploits the small -search space and cache locality. - -* The simplest example is a linear search of contiguous entries. This is - simple to implement, guaranteed to terminate rapidly, never searches - the same entry twice, and precludes the need to check for dummy entries. - -* A more advanced example is a self-organizing search so that the most - frequently accessed entries get probed first. The organization - adapts if the access pattern changes over time. Treaps are ideally - suited for self-organization with the most common entries at the - top of the heap and a rapid binary search pattern. Most probes and - results are all located at the top of the tree allowing them all to - be located in one or two cache lines. - -* Also, small dictionaries may be made more dense, perhaps filling all - eight cells to take the maximum advantage of two cache lines. - - -Strategy Pattern ----------------- - -Consider allowing the user to set the tunable parameters or to select a -particular search method. Since some dictionary use cases have known -sizes and access patterns, the user may be able to provide useful hints. - -1) For example, if membership testing or lookups dominate runtime and memory - is not at a premium, the user may benefit from setting the maximum load - ratio at 5% or 10% instead of the usual 66.7%. This will sharply - curtail the number of collisions but will increase iteration time. - The builtin namespace is a prime example of a dictionary that can - benefit from being highly sparse. - -2) Dictionary creation time can be shortened in cases where the ultimate - size of the dictionary is known in advance. The dictionary can be - pre-sized so that no resize operations are required during creation. - Not only does this save resizes, but the key insertion will go - more quickly because the first half of the keys will be inserted into - a more sparse environment than before. The preconditions for this - strategy arise whenever a dictionary is created from a key or item - sequence and the number of *unique* keys is known. - -3) If the key space is large and the access pattern is known to be random, - then search strategies exploiting cache locality can be fruitful. - The preconditions for this strategy arise in simulations and - numerical analysis. - -4) If the keys are fixed and the access pattern strongly favors some of - the keys, then the entries can be stored contiguously and accessed - with a linear search or treap. This exploits knowledge of the data, - cache locality, and a simplified search routine. It also eliminates - the need to test for dummy entries on each probe. The preconditions - for this strategy arise in symbol tables and in the builtin dictionary. - - -Readonly Dictionaries ---------------------- -Some dictionary use cases pass through a build stage and then move to a -more heavily exercised lookup stage with no further changes to the -dictionary. - -An idea that emerged on python-dev is to be able to convert a dictionary -to a read-only state. This can help prevent programming errors and also -provide knowledge that can be exploited for lookup optimization. - -The dictionary can be immediately rebuilt (eliminating dummy entries), -resized (to an appropriate level of sparseness), and the keys can be -jostled (to minimize collisions). The lookdict() routine can then -eliminate the test for dummy entries (saving about 1/4 of the time -spent in the collision resolution loop). - -An additional possibility is to insert links into the empty spaces -so that dictionary iteration can proceed in len(d) steps instead of -(mp->mask + 1) steps. Alternatively, a separate tuple of keys can be -kept just for iteration. - - -Caching Lookups ---------------- -The idea is to exploit key access patterns by anticipating future lookups -based on previous lookups. - -The simplest incarnation is to save the most recently accessed entry. -This gives optimal performance for use cases where every get is followed -by a set or del to the same key. diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -7,9 +7,93 @@ tuning dictionaries, and several ideas for possible optimizations. */ + +/* +There are four kinds of slots in the table: + +1. Unused. me_key == me_value == NULL + Does not hold an active (key, value) pair now and never did. Unused can + transition to Active upon key insertion. This is the only case in which + me_key is NULL, and is each slot's initial state. + +2. Active. me_key != NULL and me_key != dummy and me_value != NULL + Holds an active (key, value) pair. Active can transition to Dummy or + Pending upon key deletion (for combined and split tables respectively). + This is the only case in which me_value != NULL. + +3. Dummy. me_key == dummy and me_value == NULL + Previously held an active (key, value) pair, but that was deleted and an + active pair has not yet overwritten the slot. Dummy can transition to + Active upon key insertion. Dummy slots cannot be made Unused again + (cannot have me_key set to NULL), else the probe sequence in case of + collision would have no way to know they were once active. + +4. Pending. Not yet inserted or deleted from a split-table. + key != NULL, key != dummy and value == NULL + +The DictObject can be in one of two forms. +Either: + A combined table: + ma_values == NULL, dk_refcnt == 1. + Values are stored in the me_value field of the PyDictKeysObject. + Slot kind 4 is not allowed i.e. + key != NULL, key != dummy and value == NULL is illegal. +Or: + A split table: + ma_values != NULL, dk_refcnt >= 1 + Values are stored in the ma_values array. + Only string (unicode) keys are allowed, no keys are present. + +Note: .popitem() abuses the me_hash field of an Unused or Dummy slot to +hold a search finger. The me_hash field of Unused or Dummy slots has no +meaning otherwise. As a consequence of this popitem always converts the dict +to the combined-table form. +*/ + +/* PyDict_MINSIZE_SPLIT is the minimum size of a split dictionary. + * It must be a power of 2, and at least 4. + * Resizing of split dictionaries is very rare, so the saving memory is more + * important than the cost of resizing. + */ +#define PyDict_MINSIZE_SPLIT 4 + +/* PyDict_MINSIZE_COMBINED is the starting size for any new, non-split dict. + * 8 allows dicts with no more than 5 active entries; experiments suggested + * this suffices for the majority of dicts (consisting mostly of usually-small + * dicts created to pass keyword arguments). + * Making this 8, rather than 4 reduces the number of resizes for most + * dictionaries, without any significant extra memory use. + */ +#define PyDict_MINSIZE_COMBINED 8 + #include "Python.h" #include "stringlib/eq.h" +typedef struct { + /* Cached hash code of me_key. */ + Py_hash_t me_hash; + PyObject *me_key; + PyObject *me_value; /* This field is only meaningful for combined tables */ +} PyDictKeyEntry; + +typedef PyDictKeyEntry *(*dict_lookup_func) +(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr); + +struct _dictkeysobject { + Py_ssize_t dk_refcnt; + Py_ssize_t dk_size; + dict_lookup_func dk_lookup; + Py_ssize_t dk_usable; + PyDictKeyEntry dk_entries[1]; +}; + + +/* +To ensure the lookup algorithm terminates, there must be at least one Unused +slot (NULL key) in the table. +To avoid slowing down lookups on a near-full table, we resize the table when +it's USABLE_FRACTION (currently two-thirds) full. +*/ /* Set a key error with the specified argument, wrapping it in a * tuple automatically so that tuple keys are not unpacked as the @@ -25,10 +109,6 @@ Py_DECREF(tup); } -/* Define this out if you don't want conversion statistics on exit. */ -#undef SHOW_CONVERSION_COUNTS - -/* See large comment block below. This must be >= 1. */ #define PERTURB_SHIFT 5 /* @@ -126,8 +206,13 @@ */ -/* Object used as dummy key to fill deleted entries */ -static PyObject *dummy = NULL; /* Initialized by first call to newPyDictObject() */ +/* Object used as dummy key to fill deleted entries + * This could be any unique object, + * use a custom type in order to minimise coupling. +*/ +static PyObject _dummy_struct; + +#define dummy (&_dummy_struct) #ifdef Py_REF_DEBUG PyObject * @@ -138,77 +223,17 @@ #endif /* forward declarations */ -static PyDictEntry * -lookdict_unicode(PyDictObject *mp, PyObject *key, Py_hash_t hash); - -#ifdef SHOW_CONVERSION_COUNTS -static long created = 0L; -static long converted = 0L; - -static void -show_counts(void) -{ - fprintf(stderr, "created %ld string dicts\n", created); - fprintf(stderr, "converted %ld to normal dicts\n", converted); - fprintf(stderr, "%.2f%% conversion rate\n", (100.0*converted)/created); -} -#endif - -/* Debug statistic to compare allocations with reuse through the free list */ -#undef SHOW_ALLOC_COUNT -#ifdef SHOW_ALLOC_COUNT -static size_t count_alloc = 0; -static size_t count_reuse = 0; - -static void -show_alloc(void) -{ - fprintf(stderr, "Dict allocations: %" PY_FORMAT_SIZE_T "d\n", - count_alloc); - fprintf(stderr, "Dict reuse through freelist: %" PY_FORMAT_SIZE_T - "d\n", count_reuse); - fprintf(stderr, "%.2f%% reuse rate\n\n", - (100.0*count_reuse/(count_alloc+count_reuse))); -} -#endif - -/* Debug statistic to count GC tracking of dicts */ -#ifdef SHOW_TRACK_COUNT -static Py_ssize_t count_untracked = 0; -static Py_ssize_t count_tracked = 0; - -static void -show_track(void) -{ - fprintf(stderr, "Dicts created: %" PY_FORMAT_SIZE_T "d\n", - count_tracked + count_untracked); - fprintf(stderr, "Dicts tracked by the GC: %" PY_FORMAT_SIZE_T - "d\n", count_tracked); - fprintf(stderr, "%.2f%% dict tracking rate\n\n", - (100.0*count_tracked/(count_untracked+count_tracked))); -} -#endif - - -/* Initialization macros. - There are two ways to create a dict: PyDict_New() is the main C API - function, and the tp_new slot maps to dict_new(). In the latter case we - can save a little time over what PyDict_New does because it's guaranteed - that the PyDictObject struct is already zeroed out. - Everyone except dict_new() should use EMPTY_TO_MINSIZE (unless they have - an excellent reason not to). -*/ - -#define INIT_NONZERO_DICT_SLOTS(mp) do { \ - (mp)->ma_table = (mp)->ma_smalltable; \ - (mp)->ma_mask = PyDict_MINSIZE - 1; \ - } while(0) - -#define EMPTY_TO_MINSIZE(mp) do { \ - memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \ - (mp)->ma_used = (mp)->ma_fill = 0; \ - INIT_NONZERO_DICT_SLOTS(mp); \ - } while(0) +static PyDictKeyEntry *lookdict(PyDictObject *mp, PyObject *key, + Py_hash_t hash, PyObject ***value_addr); +static PyDictKeyEntry *lookdict_unicode(PyDictObject *mp, PyObject *key, + Py_hash_t hash, PyObject ***value_addr); +static PyDictKeyEntry * +lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key, + Py_hash_t hash, PyObject ***value_addr); +static PyDictKeyEntry *lookdict_split(PyDictObject *mp, PyObject *key, + Py_hash_t hash, PyObject ***value_addr); + +static int dictresize(PyDictObject *mp, Py_ssize_t minused); /* Dictionary reuse scheme to save calls to malloc, free, and memset */ #ifndef PyDict_MAXFREELIST @@ -236,61 +261,149 @@ PyDict_ClearFreeList(); } -PyObject * -PyDict_New(void) +#define DK_INCREF(dk) (++(dk)->dk_refcnt) +#define DK_DECREF(dk) if ((--(dk)->dk_refcnt) == 0) free_keys_object(dk) +#define DK_SIZE(dk) ((dk)->dk_size) +#define DK_MASK(dk) (((dk)->dk_size)-1) +#define IS_POWER_OF_2(x) (((x) & (x-1)) == 0) + +/* USABLE_FRACTION must obey the following: + * (0 < USABLE_FRACTION(n) < n) for all n >= 2 + * + * USABLE_FRACTION should be very quick to calculate. + * Fractions around 5/8 to 2/3 seem to work well in practice. + */ + +/* Use (2n+1)/3 rather than 2n+3 because: it makes no difference for + * combined tables (the two fractions round to the same number n < ), + * but 2*4/3 is 2 whereas (2*4+1)/3 is 3 which potentially saves quite + * a lot of space for small, split tables */ +#define USABLE_FRACTION(n) ((((n) << 1)+1)/3) + +/* Alternative fraction that is otherwise close enough to (2n+1)/3 to make + * little difference. 8 * 2/3 == 8 * 5/8 == 5. 16 * 2/3 == 16 * 5/8 == 10. + * 32 * 2/3 = 21, 32 * 5/8 = 20. + * Its advantage is that it is faster to compute on machines with slow division. + * #define USABLE_FRACTION(n) (((n) >> 1) + ((n) >> 2) - ((n) >> 3)) +*/ + + +#define ENSURE_ALLOWS_DELETIONS(d) \ + if ((d)->ma_keys->dk_lookup == lookdict_unicode_nodummy) { \ + (d)->ma_keys->dk_lookup = lookdict_unicode; \ + } + +/* This immutable, empty PyDictKeysObject is used for PyDict_Clear() + * (which cannot fail and thus can do no allocation). + */ +static PyDictKeysObject empty_keys_struct = { + 2, /* dk_refcnt 1 for this struct, 1 for dummy_struct */ + 1, /* dk_size */ + lookdict_split, /* dk_lookup */ + 0, /* dk_usable (immutable) */ + { + { 0, 0, 0 } /* dk_entries (empty) */ + } +}; + +static PyObject *empty_values[1] = { NULL }; + +#define Py_EMPTY_KEYS &empty_keys_struct + +static PyDictKeysObject *new_keys_object(Py_ssize_t size) { - register PyDictObject *mp; - if (dummy == NULL) { /* Auto-initialize dummy */ - dummy = PyUnicode_FromString(""); - if (dummy == NULL) - return NULL; -#ifdef SHOW_CONVERSION_COUNTS - Py_AtExit(show_counts); -#endif -#ifdef SHOW_ALLOC_COUNT - Py_AtExit(show_alloc); -#endif -#ifdef SHOW_TRACK_COUNT - Py_AtExit(show_track); -#endif + PyDictKeysObject *dk; + Py_ssize_t i; + PyDictKeyEntry *ep0; + + assert(size >= PyDict_MINSIZE_SPLIT); + assert(IS_POWER_OF_2(size)); + dk = PyMem_MALLOC(sizeof(PyDictKeysObject) + + sizeof(PyDictKeyEntry) * (size-1)); + if (dk == NULL) { + PyErr_NoMemory(); + return NULL; } + dk->dk_refcnt = 1; + dk->dk_size = size; + dk->dk_usable = USABLE_FRACTION(size); + ep0 = &dk->dk_entries[0]; + /* Hash value of slot 0 is used by popitem, so it must be initialized */ + ep0->me_hash = 0; + for (i = 0; i < size; i++) { + ep0[i].me_key = NULL; + ep0[i].me_value = NULL; + } + dk->dk_lookup = lookdict_unicode_nodummy; + return dk; +} + +static void +free_keys_object(PyDictKeysObject *keys) +{ + PyDictKeyEntry *entries = &keys->dk_entries[0]; + Py_ssize_t i, n; + for (i = 0, n = DK_SIZE(keys); i < n; i++) { + Py_XDECREF(entries[i].me_key); + Py_XDECREF(entries[i].me_value); + } + PyMem_FREE(keys); +} + +#define new_values(size) PyMem_NEW(PyObject *, size) + +#define free_values(values) PyMem_FREE(values) + +/* Consumes a reference to the keys object */ +static PyObject * +new_dict(PyDictKeysObject *keys, PyObject **values) +{ + PyDictObject *mp; if (numfree) { mp = free_list[--numfree]; assert (mp != NULL); assert (Py_TYPE(mp) == &PyDict_Type); _Py_NewReference((PyObject *)mp); - if (mp->ma_fill) { - EMPTY_TO_MINSIZE(mp); - } else { - /* At least set ma_table and ma_mask; these are wrong - if an empty but presized dict is added to freelist */ - INIT_NONZERO_DICT_SLOTS(mp); + } + else { + mp = PyObject_GC_New(PyDictObject, &PyDict_Type); + if (mp == NULL) { + DK_DECREF(keys); + free_values(values); + return NULL; } - assert (mp->ma_used == 0); - assert (mp->ma_table == mp->ma_smalltable); - assert (mp->ma_mask == PyDict_MINSIZE - 1); -#ifdef SHOW_ALLOC_COUNT - count_reuse++; -#endif - } else { - mp = PyObject_GC_New(PyDictObject, &PyDict_Type); - if (mp == NULL) - return NULL; - EMPTY_TO_MINSIZE(mp); -#ifdef SHOW_ALLOC_COUNT - count_alloc++; -#endif } - mp->ma_lookup = lookdict_unicode; -#ifdef SHOW_TRACK_COUNT - count_untracked++; -#endif -#ifdef SHOW_CONVERSION_COUNTS - ++created; -#endif + mp->ma_keys = keys; + mp->ma_values = values; + mp->ma_used = 0; return (PyObject *)mp; } +/* Consumes a reference to the keys object */ +static PyObject * +new_dict_with_shared_keys(PyDictKeysObject *keys) +{ + PyObject **values; + Py_ssize_t i, size; + + size = DK_SIZE(keys); + values = new_values(size); + if (values == NULL) { + DK_DECREF(keys); + return PyErr_NoMemory(); + } + for (i = 0; i < size; i++) { + values[i] = NULL; + } + return new_dict(keys, values); +} + +PyObject * +PyDict_New(void) +{ + return new_dict(new_keys_object(PyDict_MINSIZE_COMBINED), NULL); +} + /* The basic lookup function used by all operations. This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4. @@ -309,29 +422,32 @@ lookdict() is general-purpose, and may return NULL if (and only if) a comparison raises an exception (this was new in Python 2.5). lookdict_unicode() below is specialized to string keys, comparison of which can -never raise an exception; that function can never return NULL. For both, when -the key isn't found a PyDictEntry* is returned for which the me_value field is -NULL; this is the slot in the dict at which the key would have been found, and -the caller can (if it wishes) add the pair to the returned -PyDictEntry*. +never raise an exception; that function can never return NULL. +lookdict_unicode_nodummy is further specialized for string keys that cannot be +the value. +For both, when the key isn't found a PyDictEntry* is returned +where the key would have been found, *value_addr points to the matching value +slot. */ -static PyDictEntry * -lookdict(PyDictObject *mp, PyObject *key, register Py_hash_t hash) +static PyDictKeyEntry * +lookdict(PyDictObject *mp, PyObject *key, + Py_hash_t hash, PyObject ***value_addr) { register size_t i; register size_t perturb; - register PyDictEntry *freeslot; - register size_t mask = (size_t)mp->ma_mask; - PyDictEntry *ep0 = mp->ma_table; - register PyDictEntry *ep; + register PyDictKeyEntry *freeslot; + register size_t mask = DK_MASK(mp->ma_keys); + PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; + register PyDictKeyEntry *ep; register int cmp; PyObject *startkey; i = (size_t)hash & mask; ep = &ep0[i]; - if (ep->me_key == NULL || ep->me_key == key) + if (ep->me_key == NULL || ep->me_key == key) { + *value_addr = &ep->me_value; return ep; - + } if (ep->me_key == dummy) freeslot = ep; else { @@ -342,9 +458,11 @@ Py_DECREF(startkey); if (cmp < 0) return NULL; - if (ep0 == mp->ma_table && ep->me_key == startkey) { - if (cmp > 0) + if (ep0 == mp->ma_keys->dk_entries && ep->me_key == startkey) { + if (cmp > 0) { + *value_addr = &ep->me_value; return ep; + } } else { PyErr_SetString(PyExc_RuntimeError, @@ -360,20 +478,33 @@ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { i = (i << 2) + i + perturb + 1; ep = &ep0[i & mask]; - if (ep->me_key == NULL) - return freeslot == NULL ? ep : freeslot; - if (ep->me_key == key) + if (ep->me_key == NULL) { + if (freeslot == NULL) { + *value_addr = &ep->me_value; + return ep; + } else { + *value_addr = &freeslot->me_value; + return freeslot; + } + } + if (ep->me_key == key) { + *value_addr = &ep->me_value; return ep; + } if (ep->me_hash == hash && ep->me_key != dummy) { startkey = ep->me_key; Py_INCREF(startkey); cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); Py_DECREF(startkey); - if (cmp < 0) + if (cmp < 0) { + *value_addr = NULL; return NULL; - if (ep0 == mp->ma_table && ep->me_key == startkey) { - if (cmp > 0) + } + if (ep0 == mp->ma_keys->dk_entries && ep->me_key == startkey) { + if (cmp > 0) { + *value_addr = &ep->me_value; return ep; + } } else { PyErr_SetString(PyExc_RuntimeError, @@ -388,46 +519,39 @@ return 0; } -/* - * Hacked up version of lookdict which can assume keys are always - * unicodes; this assumption allows testing for errors during - * PyObject_RichCompareBool() to be dropped; unicode-unicode - * comparisons never raise exceptions. This also means we don't need - * to go through PyObject_RichCompareBool(); we can always use - * unicode_eq() directly. - * - * This is valuable because dicts with only unicode keys are very common. - */ -static PyDictEntry * -lookdict_unicode(PyDictObject *mp, PyObject *key, register Py_hash_t hash) +/* Specialized version for string-only keys */ +static PyDictKeyEntry * +lookdict_unicode(PyDictObject *mp, PyObject *key, + Py_hash_t hash, PyObject ***value_addr) { register size_t i; register size_t perturb; - register PyDictEntry *freeslot; - register size_t mask = (size_t)mp->ma_mask; - PyDictEntry *ep0 = mp->ma_table; - register PyDictEntry *ep; + register PyDictKeyEntry *freeslot; + register size_t mask = DK_MASK(mp->ma_keys); + PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; + register PyDictKeyEntry *ep; /* Make sure this function doesn't have to handle non-unicode keys, including subclasses of str; e.g., one reason to subclass unicodes is to override __eq__, and for speed we don't cater to that here. */ if (!PyUnicode_CheckExact(key)) { -#ifdef SHOW_CONVERSION_COUNTS - ++converted; -#endif - mp->ma_lookup = lookdict; - return lookdict(mp, key, hash); + mp->ma_keys->dk_lookup = lookdict; + return lookdict(mp, key, hash, value_addr); } i = (size_t)hash & mask; ep = &ep0[i]; - if (ep->me_key == NULL || ep->me_key == key) + if (ep->me_key == NULL || ep->me_key == key) { + *value_addr = &ep->me_value; return ep; + } if (ep->me_key == dummy) freeslot = ep; else { - if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) + if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { + *value_addr = &ep->me_value; return ep; + } freeslot = NULL; } @@ -436,13 +560,22 @@ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { i = (i << 2) + i + perturb + 1; ep = &ep0[i & mask]; - if (ep->me_key == NULL) - return freeslot == NULL ? ep : freeslot; + if (ep->me_key == NULL) { + if (freeslot == NULL) { + *value_addr = &ep->me_value; + return ep; + } else { + *value_addr = &freeslot->me_value; + return freeslot; + } + } if (ep->me_key == key || (ep->me_hash == hash && ep->me_key != dummy - && unicode_eq(ep->me_key, key))) + && unicode_eq(ep->me_key, key))) { + *value_addr = &ep->me_value; return ep; + } if (ep->me_key == dummy && freeslot == NULL) freeslot = ep; } @@ -450,6 +583,88 @@ return 0; } +/* Faster version of lookdict_unicode when it is known that no keys + * will be present. */ +static PyDictKeyEntry * +lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key, + Py_hash_t hash, PyObject ***value_addr) +{ + register size_t i; + register size_t perturb; + register size_t mask = DK_MASK(mp->ma_keys); + PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; + register PyDictKeyEntry *ep; + + /* Make sure this function doesn't have to handle non-unicode keys, + including subclasses of str; e.g., one reason to subclass + unicodes is to override __eq__, and for speed we don't cater to + that here. */ + if (!PyUnicode_CheckExact(key)) { + mp->ma_keys->dk_lookup = lookdict; + return lookdict(mp, key, hash, value_addr); + } + i = (size_t)hash & mask; + ep = &ep0[i]; + assert(ep->me_key == NULL || PyUnicode_CheckExact(ep->me_key)); + if (ep->me_key == NULL || ep->me_key == key || + (ep->me_hash == hash && unicode_eq(ep->me_key, key))) { + *value_addr = &ep->me_value; + return ep; + } + for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + i = (i << 2) + i + perturb + 1; + ep = &ep0[i & mask]; + assert(ep->me_key == NULL || PyUnicode_CheckExact(ep->me_key)); + if (ep->me_key == NULL || ep->me_key == key || + (ep->me_hash == hash && unicode_eq(ep->me_key, key))) { + *value_addr = &ep->me_value; + return ep; + } + } + assert(0); /* NOT REACHED */ + return 0; +} + +/* Version of lookdict for split tables. + * All split tables and only split tables use this lookup function. + * Split tables only contain unicode keys and no dummy keys, + * so algorithm is the same as lookdict_unicode_nodummy. + */ +static PyDictKeyEntry * +lookdict_split(PyDictObject *mp, PyObject *key, + Py_hash_t hash, PyObject ***value_addr) +{ + register size_t i; + register size_t perturb; + register size_t mask = DK_MASK(mp->ma_keys); + PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; + register PyDictKeyEntry *ep; + + if (!PyUnicode_CheckExact(key)) { + return lookdict(mp, key, hash, value_addr); + } + i = (size_t)hash & mask; + ep = &ep0[i]; + assert(ep->me_key == NULL || PyUnicode_CheckExact(ep->me_key)); + if (ep->me_key == NULL || ep->me_key == key || + (ep->me_hash == hash && unicode_eq(ep->me_key, key))) { + *value_addr = &mp->ma_values[i]; + return ep; + } + for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + i = (i << 2) + i + perturb + 1; + ep = &ep0[i & mask]; + assert(ep->me_key == NULL || PyUnicode_CheckExact(ep->me_key)); + if (ep->me_key == NULL || ep->me_key == key || + (ep->me_hash == hash && unicode_eq(ep->me_key, key))) { + *value_addr = &mp->ma_values[i & mask]; + return ep; + } + } + assert(0); /* NOT REACHED */ + return 0; +} + int _PyDict_HasOnlyStringKeys(PyObject *dict) { @@ -457,7 +672,7 @@ PyObject *key, *value; assert(PyDict_Check(dict)); /* Shortcut */ - if (((PyDictObject *)dict)->ma_lookup == lookdict_unicode) + if (((PyDictObject *)dict)->ma_keys->dk_lookup != lookdict) return 1; while (PyDict_Next(dict, &pos, &key, &value)) if (!PyUnicode_Check(key)) @@ -465,23 +680,12 @@ return 1; } -#ifdef SHOW_TRACK_COUNT -#define INCREASE_TRACK_COUNT \ - (count_tracked++, count_untracked--); -#define DECREASE_TRACK_COUNT \ - (count_tracked--, count_untracked++); -#else -#define INCREASE_TRACK_COUNT -#define DECREASE_TRACK_COUNT -#endif - #define MAINTAIN_TRACKING(mp, key, value) \ do { \ if (!_PyObject_GC_IS_TRACKED(mp)) { \ if (_PyObject_GC_MAY_BE_TRACKED(key) || \ _PyObject_GC_MAY_BE_TRACKED(value)) { \ _PyObject_GC_TRACK(mp); \ - INCREASE_TRACK_COUNT \ } \ } \ } while(0) @@ -491,59 +695,79 @@ { PyDictObject *mp; PyObject *value; - Py_ssize_t mask, i; - PyDictEntry *ep; + Py_ssize_t i, size; if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op)) return; mp = (PyDictObject *) op; - ep = mp->ma_table; - mask = mp->ma_mask; - for (i = 0; i <= mask; i++) { - if ((value = ep[i].me_value) == NULL) - continue; - if (_PyObject_GC_MAY_BE_TRACKED(value) || - _PyObject_GC_MAY_BE_TRACKED(ep[i].me_key)) - return; + size = DK_SIZE(mp->ma_keys); + if (_PyDict_HasSplitTable(mp)) { + for (i = 0; i < size; i++) { + if ((value = mp->ma_values[i]) == NULL) + continue; + if (_PyObject_GC_MAY_BE_TRACKED(value)) { + assert(!_PyObject_GC_MAY_BE_TRACKED( + mp->ma_keys->dk_entries[i].me_key)); + return; + } + } } - DECREASE_TRACK_COUNT + else { + PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; + for (i = 0; i < size; i++) { + if ((value = ep0[i].me_value) == NULL) + continue; + if (_PyObject_GC_MAY_BE_TRACKED(value) || + _PyObject_GC_MAY_BE_TRACKED(ep0[i].me_key)) + return; + } + } _PyObject_GC_UNTRACK(op); } -/* -Internal routine to insert a new item into the table when you have entry object. -Used by insertdict. -*/ +/* Internal function to find slot for an item from its hash + * when it is known that the key is not present in the dict. + */ +static PyDictKeyEntry * +find_empty_slot(PyDictObject *mp, PyObject *key, Py_hash_t hash, + PyObject ***value_addr) +{ + size_t i; + size_t perturb; + size_t mask = DK_MASK(mp->ma_keys); + PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; + PyDictKeyEntry *ep; + + assert(key != NULL); + if (!PyUnicode_CheckExact(key)) + mp->ma_keys->dk_lookup = lookdict; + i = hash & mask; + ep = &ep0[i]; + for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) { + i = (i << 2) + i + perturb + 1; + ep = &ep0[i & mask]; + } + assert(ep->me_value == NULL); + if (mp->ma_values) + *value_addr = &mp->ma_values[i & mask]; + else + *value_addr = &ep->me_value; + return ep; +} + static int -insertdict_by_entry(register PyDictObject *mp, PyObject *key, Py_hash_t hash, - PyDictEntry *ep, PyObject *value) +insertion_resize(PyDictObject *mp) { - PyObject *old_value; - - MAINTAIN_TRACKING(mp, key, value); - if (ep->me_value != NULL) { - old_value = ep->me_value; - ep->me_value = value; - Py_DECREF(old_value); /* which **CAN** re-enter */ - Py_DECREF(key); - } - else { - if (ep->me_key == NULL) - mp->ma_fill++; - else { - assert(ep->me_key == dummy); - Py_DECREF(dummy); - } - ep->me_key = key; - ep->me_hash = hash; - ep->me_value = value; - mp->ma_used++; - } - return 0; + /* + * Double the size of the dict, + * Previous versions quadrupled size, but doing so may result in excessive + * memory use. Doubling keeps the number of resizes low without wasting + * too much memory. + */ + return dictresize(mp, 2 * mp->ma_used); } - /* Internal routine to insert a new item into the table. Used both by the internal resize routine and by the public insert routine. @@ -551,18 +775,64 @@ Returns -1 if an error occurred, or 0 on success. */ static int -insertdict(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) +insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { - register PyDictEntry *ep; - - assert(mp->ma_lookup != NULL); - ep = mp->ma_lookup(mp, key, hash); + PyObject *old_value; + PyObject **value_addr; + PyDictKeyEntry *ep; + assert(key != dummy); + + if (mp->ma_values != NULL && !PyUnicode_CheckExact(key)) { + if (insertion_resize(mp) < 0) + return -1; + } + + ep = mp->ma_keys->dk_lookup(mp, key, hash, &value_addr); if (ep == NULL) { Py_DECREF(key); Py_DECREF(value); return -1; } - return insertdict_by_entry(mp, key, hash, ep, value); + MAINTAIN_TRACKING(mp, key, value); + old_value = *value_addr; + if (old_value != NULL) { + assert(ep->me_key != NULL && ep->me_key != dummy); + *value_addr = value; + Py_DECREF(old_value); /* which **CAN** re-enter */ + Py_DECREF(key); + } + else { + if (ep->me_key == NULL) { + if (mp->ma_keys->dk_usable <= 0) { + /* Need to resize. */ + if (insertion_resize(mp) < 0) { + Py_DECREF(key); + Py_DECREF(value); + return -1; + } + ep = find_empty_slot(mp, key, hash, &value_addr); + } + mp->ma_keys->dk_usable--; + assert(mp->ma_keys->dk_usable >= 0); + ep->me_key = key; + ep->me_hash = hash; + } + else { + if (ep->me_key == dummy) { + ep->me_key = key; + ep->me_hash = hash; + Py_DECREF(dummy); + } else { + Py_DECREF(key); + assert(_PyDict_HasSplitTable(mp)); + } + } + mp->ma_used++; + *value_addr = value; + } + assert(ep->me_key != NULL && ep->me_key != dummy); + assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict); + return 0; } /* @@ -572,50 +842,57 @@ using insertdict() in dictresize() is dangerous (SF bug #1456209). Note that no refcounts are changed by this routine; if needed, the caller is responsible for incref'ing `key` and `value`. +Neither mp->ma_used nor k->dk_usable are modified by this routine; the caller +must set them correctly */ static void -insertdict_clean(register PyDictObject *mp, PyObject *key, Py_hash_t hash, +insertdict_clean(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { - register size_t i; - register size_t perturb; - register size_t mask = (size_t)mp->ma_mask; - PyDictEntry *ep0 = mp->ma_table; - register PyDictEntry *ep; - - MAINTAIN_TRACKING(mp, key, value); - i = (size_t)hash & mask; + size_t i; + size_t perturb; + PyDictKeysObject *k = mp->ma_keys; + size_t mask = (size_t)DK_SIZE(k)-1; + PyDictKeyEntry *ep0 = &k->dk_entries[0]; + PyDictKeyEntry *ep; + + assert(k->dk_lookup != NULL); + assert(value != NULL); + assert(key != NULL); + assert(key != dummy); + assert(PyUnicode_CheckExact(key) || k->dk_lookup == lookdict); + i = hash & mask; ep = &ep0[i]; for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) { i = (i << 2) + i + perturb + 1; ep = &ep0[i & mask]; } assert(ep->me_value == NULL); - mp->ma_fill++; ep->me_key = key; ep->me_hash = hash; ep->me_value = value; - mp->ma_used++; } /* Restructure the table by allocating a new table and reinserting all items again. When entries have been deleted, the new table may actually be smaller than the old one. +If a table is split (its keys and hashes are shared, its values are not), +then the values are temporarily copied into the table, it is resized as +a combined table, then the me_value slots in the old table are NULLed out. +After resizing a table is always combined, +but can be resplit by make_keys_shared(). */ static int dictresize(PyDictObject *mp, Py_ssize_t minused) { Py_ssize_t newsize; - PyDictEntry *oldtable, *newtable, *ep; - Py_ssize_t i; - int is_oldtable_malloced; - PyDictEntry small_copy[PyDict_MINSIZE]; - - assert(minused >= 0); - - /* Find the smallest table size > minused. */ - for (newsize = PyDict_MINSIZE; + PyDictKeysObject *oldkeys; + PyObject **oldvalues; + Py_ssize_t i, oldsize; + +/* Find the smallest table size > minused. */ + for (newsize = PyDict_MINSIZE_COMBINED; newsize <= minused && newsize > 0; newsize <<= 1) ; @@ -623,83 +900,122 @@ PyErr_NoMemory(); return -1; } - - /* Get space for a new table. */ - oldtable = mp->ma_table; - assert(oldtable != NULL); - is_oldtable_malloced = oldtable != mp->ma_smalltable; - - if (newsize == PyDict_MINSIZE) { - /* A large table is shrinking, or we can't get any smaller. */ - newtable = mp->ma_smalltable; - if (newtable == oldtable) { - if (mp->ma_fill == mp->ma_used) { - /* No dummies, so no point doing anything. */ - return 0; + oldkeys = mp->ma_keys; + oldvalues = mp->ma_values; + /* Allocate a new table. */ + mp->ma_keys = new_keys_object(newsize); + if (mp->ma_keys == NULL) { + mp->ma_keys = oldkeys; + return -1; + } + if (oldkeys->dk_lookup == lookdict) + mp->ma_keys->dk_lookup = lookdict; + oldsize = DK_SIZE(oldkeys); + mp->ma_values = NULL; + /* If empty then nothing to copy so just return */ + if (oldsize == 1) { + assert(oldkeys == Py_EMPTY_KEYS); + DK_DECREF(oldkeys); + return 0; + } + /* Main loop below assumes we can transfer refcount to new keys + * and that value is stored in me_value. + * Increment ref-counts and copy values here to compensate + * This (resizing a split table) should be relatively rare */ + if (oldvalues != NULL) { + for (i = 0; i < oldsize; i++) { + if (oldvalues[i] != NULL) { + Py_INCREF(oldkeys->dk_entries[i].me_key); + oldkeys->dk_entries[i].me_value = oldvalues[i]; } - /* We're not going to resize it, but rebuild the - table anyway to purge old dummy entries. - Subtle: This is *necessary* if fill==size, - as lookdict needs at least one virgin slot to - terminate failing searches. If fill < size, it's - merely desirable, as dummies slow searches. */ - assert(mp->ma_fill > mp->ma_used); - memcpy(small_copy, oldtable, sizeof(small_copy)); - oldtable = small_copy; } } - else { - newtable = PyMem_NEW(PyDictEntry, newsize); - if (newtable == NULL) { - PyErr_NoMemory(); - return -1; + /* Main loop */ + for (i = 0; i < oldsize; i++) { + PyDictKeyEntry *ep = &oldkeys->dk_entries[i]; + if (ep->me_value != NULL) { + assert(ep->me_key != dummy); + insertdict_clean(mp, ep->me_key, ep->me_hash, ep->me_value); } } - - /* Make the dict empty, using the new table. */ - assert(newtable != oldtable); - mp->ma_table = newtable; - mp->ma_mask = newsize - 1; - memset(newtable, 0, sizeof(PyDictEntry) * newsize); - mp->ma_used = 0; - i = mp->ma_fill; - mp->ma_fill = 0; - - /* Copy the data over; this is refcount-neutral for active entries; - dummy entries aren't copied over, of course */ - for (ep = oldtable; i > 0; ep++) { - if (ep->me_value != NULL) { /* active entry */ - --i; - insertdict_clean(mp, ep->me_key, ep->me_hash, ep->me_value); + mp->ma_keys->dk_usable -= mp->ma_used; + if (oldvalues != NULL) { + /* NULL out me_value slot in oldkeys, in case it was shared */ + for (i = 0; i < oldsize; i++) + oldkeys->dk_entries[i].me_value = NULL; + assert(oldvalues != empty_values); + free_values(oldvalues); + DK_DECREF(oldkeys); + } + else { + assert(oldkeys->dk_lookup != lookdict_split); + if (oldkeys->dk_lookup != lookdict_unicode_nodummy) { + PyDictKeyEntry *ep0 = &oldkeys->dk_entries[0]; + for (i = 0; i < oldsize; i++) { + if (ep0[i].me_key == dummy) + Py_DECREF(dummy); + } } - else if (ep->me_key != NULL) { /* dummy entry */ - --i; - assert(ep->me_key == dummy); - Py_DECREF(ep->me_key); - } - /* else key == value == NULL: nothing to do */ + assert(oldkeys->dk_refcnt == 1); + PyMem_FREE(oldkeys); } - - if (is_oldtable_malloced) - PyMem_DEL(oldtable); return 0; } -/* Create a new dictionary pre-sized to hold an estimated number of elements. - Underestimates are okay because the dictionary will resize as necessary. - Overestimates just mean the dictionary will be more sparse than usual. -*/ +static PyDictKeysObject * +make_keys_shared(PyObject *op) +{ + Py_ssize_t i; + Py_ssize_t size; + PyDictObject *mp = (PyDictObject *)op; + + assert(PyDict_CheckExact(op)); + if (!_PyDict_HasSplitTable(mp)) { + PyDictKeyEntry *ep0; + PyObject **values; + assert(mp->ma_keys->dk_refcnt == 1); + if (mp->ma_keys->dk_lookup == lookdict) { + return NULL; + } + else if (mp->ma_keys->dk_lookup == lookdict_unicode) { + /* Remove dummy keys */ + if (dictresize(mp, DK_SIZE(mp->ma_keys))) + return NULL; + } + assert(mp->ma_keys->dk_lookup == lookdict_unicode_nodummy); + /* Copy values into a new array */ + ep0 = &mp->ma_keys->dk_entries[0]; + size = DK_SIZE(mp->ma_keys); + values = new_values(size); + if (values == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Not enough memory to allocate new values array"); + return NULL; + } + for (i = 0; i < size; i++) { + values[i] = ep0[i].me_value; + ep0[i].me_value = NULL; + } + mp->ma_keys->dk_lookup = lookdict_split; + mp->ma_values = values; + } + DK_INCREF(mp->ma_keys); + return mp->ma_keys; +} PyObject * _PyDict_NewPresized(Py_ssize_t minused) { - PyObject *op = PyDict_New(); - - if (minused>5 && op != NULL && dictresize((PyDictObject *)op, minused) == -1) { - Py_DECREF(op); + Py_ssize_t newsize; + PyDictKeysObject *new_keys; + for (newsize = PyDict_MINSIZE_COMBINED; + newsize <= minused && newsize > 0; + newsize <<= 1) + ; + new_keys = new_keys_object(newsize); + if (new_keys == NULL) return NULL; - } - return op; + return new_dict(new_keys, NULL); } /* Note that, for historical reasons, PyDict_GetItem() suppresses all errors @@ -717,8 +1033,10 @@ { Py_hash_t hash; PyDictObject *mp = (PyDictObject *)op; - PyDictEntry *ep; + PyDictKeyEntry *ep; PyThreadState *tstate; + PyObject **value_addr; + if (!PyDict_Check(op)) return NULL; if (!PyUnicode_CheckExact(key) || @@ -742,20 +1060,20 @@ /* preserve the existing exception */ PyObject *err_type, *err_value, *err_tb; PyErr_Fetch(&err_type, &err_value, &err_tb); - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); /* ignore errors */ PyErr_Restore(err_type, err_value, err_tb); if (ep == NULL) return NULL; } else { - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) { PyErr_Clear(); return NULL; } } - return ep->me_value; + return *value_addr; } /* Variant of PyDict_GetItem() that doesn't suppress exceptions. @@ -767,7 +1085,8 @@ { Py_hash_t hash; PyDictObject*mp = (PyDictObject *)op; - PyDictEntry *ep; + PyDictKeyEntry *ep; + PyObject **value_addr; if (!PyDict_Check(op)) { PyErr_BadInternalCall(); @@ -782,10 +1101,10 @@ } } - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) return NULL; - return ep->me_value; + return *value_addr; } PyObject * @@ -798,43 +1117,39 @@ return PyDict_GetItemWithError(dp, kv); } -static int -dict_set_item_by_hash_or_entry(register PyObject *op, PyObject *key, - Py_hash_t hash, PyDictEntry *ep, PyObject *value) +/* Fast version of global value lookup. + * Lookup in globals, then builtins. + */ +PyObject * +_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key) { - register PyDictObject *mp; - register Py_ssize_t n_used; - - mp = (PyDictObject *)op; - assert(mp->ma_fill <= mp->ma_mask); /* at least one empty slot */ - n_used = mp->ma_used; - Py_INCREF(value); - Py_INCREF(key); - if (ep == NULL) { - if (insertdict(mp, key, hash, value) != 0) - return -1; + PyObject *x; + if (PyUnicode_CheckExact(key)) { + PyObject **value_addr; + Py_hash_t hash = ((PyASCIIObject *)key)->hash; + if (hash != -1) { + PyDictKeyEntry *e; + e = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr); + if (e == NULL) { + return NULL; + } + x = *value_addr; + if (x != NULL) + return x; + e = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr); + if (e == NULL) { + return NULL; + } + x = *value_addr; + return x; + } } - else { - if (insertdict_by_entry(mp, key, hash, ep, value) != 0) - return -1; - } - /* If we added a key, we can safely resize. Otherwise just return! - * If fill >= 2/3 size, adjust size. Normally, this doubles or - * quaduples the size, but it's also possible for the dict to shrink - * (if ma_fill is much larger than ma_used, meaning a lot of dict - * keys have been * deleted). - * - * Quadrupling the size improves average dictionary sparseness - * (reducing collisions) at the cost of some memory and iteration - * speed (which loops over every possible entry). It also halves - * the number of expensive resize operations in a growing dictionary. - * - * Very large dictionaries (over 50K items) use doubling instead. - * This may help applications with severe memory constraints. - */ - if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2)) - return 0; - return dictresize(mp, (mp->ma_used > 50000 ? 2 : 4) * mp->ma_used); + x = PyDict_GetItemWithError((PyObject *)globals, key); + if (x != NULL) + return x; + if (PyErr_Occurred()) + return NULL; + return PyDict_GetItemWithError((PyObject *)builtins, key); } /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the @@ -844,36 +1159,39 @@ * remove them. */ int -PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value) +PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) { - register Py_hash_t hash; - + PyDictObject *mp; + Py_hash_t hash; if (!PyDict_Check(op)) { PyErr_BadInternalCall(); return -1; } assert(key); assert(value); - if (PyUnicode_CheckExact(key)) { - hash = ((PyASCIIObject *) key)->hash; - if (hash == -1) - hash = PyObject_Hash(key); - } - else { + mp = (PyDictObject *)op; + if (!PyUnicode_CheckExact(key) || + (hash = ((PyASCIIObject *) key)->hash) == -1) + { hash = PyObject_Hash(key); if (hash == -1) return -1; } - return dict_set_item_by_hash_or_entry(op, key, hash, NULL, value); + Py_INCREF(value); + Py_INCREF(key); + + /* insertdict() handles any resizing that might be necessary */ + return insertdict(mp, key, hash, value); } int PyDict_DelItem(PyObject *op, PyObject *key) { - register PyDictObject *mp; - register Py_hash_t hash; - register PyDictEntry *ep; - PyObject *old_value, *old_key; + PyDictObject *mp; + Py_hash_t hash; + PyDictKeyEntry *ep; + PyObject *old_key, *old_value; + PyObject **value_addr; if (!PyDict_Check(op)) { PyErr_BadInternalCall(); @@ -887,21 +1205,24 @@ return -1; } mp = (PyDictObject *)op; - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) return -1; - if (ep->me_value == NULL) { + if (*value_addr == NULL) { set_key_error(key); return -1; } - old_key = ep->me_key; - Py_INCREF(dummy); - ep->me_key = dummy; - old_value = ep->me_value; - ep->me_value = NULL; + old_value = *value_addr; + *value_addr = NULL; mp->ma_used--; + if (!_PyDict_HasSplitTable(mp)) { + ENSURE_ALLOWS_DELETIONS(mp); + old_key = ep->me_key; + Py_INCREF(dummy); + ep->me_key = dummy; + Py_DECREF(old_key); + } Py_DECREF(old_value); - Py_DECREF(old_key); return 0; } @@ -909,69 +1230,70 @@ PyDict_Clear(PyObject *op) { PyDictObject *mp; - PyDictEntry *ep, *table; - int table_is_malloced; - Py_ssize_t fill; - PyDictEntry small_copy[PyDict_MINSIZE]; -#ifdef Py_DEBUG + PyDictKeysObject *oldkeys; + PyObject **oldvalues; Py_ssize_t i, n; -#endif if (!PyDict_Check(op)) return; + mp = ((PyDictObject *)op); + oldkeys = mp->ma_keys; + oldvalues = mp->ma_values; + if (oldvalues == empty_values) + return; + /* Empty the dict... */ + DK_INCREF(Py_EMPTY_KEYS); + mp->ma_keys = Py_EMPTY_KEYS; + mp->ma_values = empty_values; + mp->ma_used = 0; + /* ...then clear the keys and values */ + if (oldvalues != NULL) { + n = DK_SIZE(oldkeys); + for (i = 0; i < n; i++) + Py_CLEAR(oldvalues[i]); + free_values(oldvalues); + DK_DECREF(oldkeys); + } + else { + assert(oldkeys->dk_refcnt == 1); + free_keys_object(oldkeys); + } +} + +/* Returns -1 if no more items (or op is not a dict), + * index of item otherwise. Stores value in pvalue + */ +Py_LOCAL_INLINE(Py_ssize_t) +dict_next(PyObject *op, Py_ssize_t i, PyObject **pvalue) +{ + Py_ssize_t mask, offset; + PyDictObject *mp; + PyObject **value_ptr; + + + if (!PyDict_Check(op)) + return -1; mp = (PyDictObject *)op; -#ifdef Py_DEBUG - n = mp->ma_mask + 1; - i = 0; -#endif - - table = mp->ma_table; - assert(table != NULL); - table_is_malloced = table != mp->ma_smalltable; - - /* This is delicate. During the process of clearing the dict, - * decrefs can cause the dict to mutate. To avoid fatal confusion - * (voice of experience), we have to make the dict empty before - * clearing the slots, and never refer to anything via mp->xxx while - * clearing. - */ - fill = mp->ma_fill; - if (table_is_malloced) - EMPTY_TO_MINSIZE(mp); - - else if (fill > 0) { - /* It's a small table with something that needs to be cleared. - * Afraid the only safe way is to copy the dict entries into - * another small table first. - */ - memcpy(small_copy, table, sizeof(small_copy)); - table = small_copy; - EMPTY_TO_MINSIZE(mp); + if (i < 0) + return -1; + if (mp->ma_values) { + value_ptr = &mp->ma_values[i]; + offset = sizeof(PyObject *); } - /* else it's a small table that's already empty */ - - /* Now we can finally clear things. If C had refcounts, we could - * assert that the refcount on table is 1 now, i.e. that this function - * has unique access to it, so decref side-effects can't alter it. - */ - for (ep = table; fill > 0; ++ep) { -#ifdef Py_DEBUG - assert(i < n); - ++i; -#endif - if (ep->me_key) { - --fill; - Py_DECREF(ep->me_key); - Py_XDECREF(ep->me_value); - } -#ifdef Py_DEBUG - else - assert(ep->me_value == NULL); -#endif + else { + value_ptr = &mp->ma_keys->dk_entries[i].me_value; + offset = sizeof(PyDictKeyEntry); } - - if (table_is_malloced) - PyMem_DEL(table); + mask = DK_MASK(mp->ma_keys); + while (i <= mask && *value_ptr == NULL) { + value_ptr = (PyObject **)(((char *)value_ptr) + offset); + i++; + } + if (i > mask) + return -1; + if (pvalue) + *pvalue = *value_ptr; + return i; } /* @@ -992,75 +1314,58 @@ int PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) { - register Py_ssize_t i; - register Py_ssize_t mask; - register PyDictEntry *ep; - - if (!PyDict_Check(op)) - return 0; - i = *ppos; + PyDictObject *mp; + Py_ssize_t i = dict_next(op, *ppos, pvalue); if (i < 0) return 0; - ep = ((PyDictObject *)op)->ma_table; - mask = ((PyDictObject *)op)->ma_mask; - while (i <= mask && ep[i].me_value == NULL) - i++; + mp = (PyDictObject *)op; *ppos = i+1; - if (i > mask) - return 0; if (pkey) - *pkey = ep[i].me_key; - if (pvalue) - *pvalue = ep[i].me_value; + *pkey = mp->ma_keys->dk_entries[i].me_key; return 1; } -/* Internal version of PyDict_Next that returns a hash value in addition to the key and value.*/ +/* Internal version of PyDict_Next that returns a hash value in addition + * to the key and value. + */ int -_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, Py_hash_t *phash) +_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, + PyObject **pvalue, Py_hash_t *phash) { - register Py_ssize_t i; - register Py_ssize_t mask; - register PyDictEntry *ep; - - if (!PyDict_Check(op)) - return 0; - i = *ppos; + PyDictObject *mp; + Py_ssize_t i = dict_next(op, *ppos, pvalue); if (i < 0) return 0; - ep = ((PyDictObject *)op)->ma_table; - mask = ((PyDictObject *)op)->ma_mask; - while (i <= mask && ep[i].me_value == NULL) - i++; + mp = (PyDictObject *)op; *ppos = i+1; - if (i > mask) - return 0; - *phash = ep[i].me_hash; + *phash = mp->ma_keys->dk_entries[i].me_hash; if (pkey) - *pkey = ep[i].me_key; - if (pvalue) - *pvalue = ep[i].me_value; + *pkey = mp->ma_keys->dk_entries[i].me_key; return 1; } /* Methods */ static void -dict_dealloc(register PyDictObject *mp) +dict_dealloc(PyDictObject *mp) { - register PyDictEntry *ep; - Py_ssize_t fill = mp->ma_fill; + PyObject **values = mp->ma_values; + PyDictKeysObject *keys = mp->ma_keys; + Py_ssize_t i, n; PyObject_GC_UnTrack(mp); Py_TRASHCAN_SAFE_BEGIN(mp) - for (ep = mp->ma_table; fill > 0; ep++) { - if (ep->me_key) { - --fill; - Py_DECREF(ep->me_key); - Py_XDECREF(ep->me_value); + if (values != NULL) { + if (values != empty_values) { + for (i = 0, n = DK_SIZE(mp->ma_keys); i < n; i++) { + Py_XDECREF(values[i]); + } + free_values(values); } + DK_DECREF(keys); } - if (mp->ma_table != mp->ma_smalltable) - PyMem_DEL(mp->ma_table); + else { + free_keys_object(keys); + } if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type) free_list[numfree++] = mp; else @@ -1068,6 +1373,7 @@ Py_TRASHCAN_SAFE_END(mp) } + static PyObject * dict_repr(PyDictObject *mp) { @@ -1099,11 +1405,13 @@ i = 0; while (PyDict_Next((PyObject *)mp, &i, &key, &value)) { int status; - /* Prevent repr from deleting value during key format. */ + /* Prevent repr from deleting key or value during key format. */ + Py_INCREF(key); Py_INCREF(value); s = PyObject_Repr(key); PyUnicode_Append(&s, colon); PyUnicode_AppendAndDel(&s, PyObject_Repr(value)); + Py_DECREF(key); Py_DECREF(value); if (s == NULL) goto Done; @@ -1158,18 +1466,19 @@ { PyObject *v; Py_hash_t hash; - PyDictEntry *ep; - assert(mp->ma_table != NULL); + PyDictKeyEntry *ep; + PyObject **value_addr; + if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *) key)->hash) == -1) { hash = PyObject_Hash(key); if (hash == -1) return NULL; } - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) return NULL; - v = ep->me_value; + v = *value_addr; if (v == NULL) { if (!PyDict_CheckExact(mp)) { /* Look up __missing__ method if we're a subclass. */ @@ -1213,8 +1522,9 @@ { register PyObject *v; register Py_ssize_t i, j; - PyDictEntry *ep; - Py_ssize_t mask, n; + PyDictKeyEntry *ep; + Py_ssize_t size, n, offset; + PyObject **value_ptr; again: n = mp->ma_used; @@ -1228,15 +1538,24 @@ Py_DECREF(v); goto again; } - ep = mp->ma_table; - mask = mp->ma_mask; - for (i = 0, j = 0; i <= mask; i++) { - if (ep[i].me_value != NULL) { + ep = &mp->ma_keys->dk_entries[0]; + size = DK_SIZE(mp->ma_keys); + if (mp->ma_values) { + value_ptr = mp->ma_values; + offset = sizeof(PyObject *); + } + else { + value_ptr = &ep[0].me_value; + offset = sizeof(PyDictKeyEntry); + } + for (i = 0, j = 0; i < size; i++) { + if (*value_ptr != NULL) { PyObject *key = ep[i].me_key; Py_INCREF(key); PyList_SET_ITEM(v, j, key); j++; } + value_ptr = (PyObject **)(((char *)value_ptr) + offset); } assert(j == n); return v; @@ -1247,8 +1566,8 @@ { register PyObject *v; register Py_ssize_t i, j; - PyDictEntry *ep; - Py_ssize_t mask, n; + Py_ssize_t size, n, offset; + PyObject **value_ptr; again: n = mp->ma_used; @@ -1262,11 +1581,19 @@ Py_DECREF(v); goto again; } - ep = mp->ma_table; - mask = mp->ma_mask; - for (i = 0, j = 0; i <= mask; i++) { - if (ep[i].me_value != NULL) { - PyObject *value = ep[i].me_value; + size = DK_SIZE(mp->ma_keys); + if (mp->ma_values) { + value_ptr = mp->ma_values; + offset = sizeof(PyObject *); + } + else { + value_ptr = &mp->ma_keys->dk_entries[0].me_value; + offset = sizeof(PyDictKeyEntry); + } + for (i = 0, j = 0; i < size; i++) { + PyObject *value = *value_ptr; + value_ptr = (PyObject **)(((char *)value_ptr) + offset); + if (value != NULL) { Py_INCREF(value); PyList_SET_ITEM(v, j, value); j++; @@ -1281,9 +1608,10 @@ { register PyObject *v; register Py_ssize_t i, j, n; - Py_ssize_t mask; - PyObject *item, *key, *value; - PyDictEntry *ep; + Py_ssize_t size, offset; + PyObject *item, *key; + PyDictKeyEntry *ep; + PyObject **value_ptr; /* Preallocate the list of tuples, to avoid allocations during * the loop over the items, which could trigger GC, which @@ -1310,10 +1638,20 @@ goto again; } /* Nothing we do below makes any function calls. */ - ep = mp->ma_table; - mask = mp->ma_mask; - for (i = 0, j = 0; i <= mask; i++) { - if ((value=ep[i].me_value) != NULL) { + ep = mp->ma_keys->dk_entries; + size = DK_SIZE(mp->ma_keys); + if (mp->ma_values) { + value_ptr = mp->ma_values; + offset = sizeof(PyObject *); + } + else { + value_ptr = &ep[0].me_value; + offset = sizeof(PyDictKeyEntry); + } + for (i = 0, j = 0; i < size; i++) { + PyObject *value = *value_ptr; + value_ptr = (PyObject **)(((char *)value_ptr) + offset); + if (value != NULL) { key = ep[i].me_key; item = PyList_GET_ITEM(v, j); Py_INCREF(key); @@ -1545,8 +1883,8 @@ PyDict_Merge(PyObject *a, PyObject *b, int override) { register PyDictObject *mp, *other; - register Py_ssize_t i; - PyDictEntry *entry; + register Py_ssize_t i, n; + PyDictKeyEntry *entry; /* We accept for the argument either a concrete dictionary object, * or an abstract "mapping" object. For the former, we can do @@ -1573,20 +1911,25 @@ * incrementally resizing as we insert new items. Expect * that there will be no (or few) overlapping keys. */ - if ((mp->ma_fill + other->ma_used)*3 >= (mp->ma_mask+1)*2) { - if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0) + if (mp->ma_keys->dk_usable * 3 < other->ma_used * 2) + if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0) return -1; - } - for (i = 0; i <= other->ma_mask; i++) { - entry = &other->ma_table[i]; - if (entry->me_value != NULL && + for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) { + PyObject *value; + entry = &other->ma_keys->dk_entries[i]; + if (other->ma_values) + value = other->ma_values[i]; + else + value = entry->me_value; + + if (value != NULL && (override || PyDict_GetItem(a, entry->me_key) == NULL)) { Py_INCREF(entry->me_key); - Py_INCREF(entry->me_value); + Py_INCREF(value); if (insertdict(mp, entry->me_key, entry->me_hash, - entry->me_value) != 0) + value) != 0) return -1; } } @@ -1648,11 +1991,35 @@ PyDict_Copy(PyObject *o) { PyObject *copy; + PyDictObject *mp; + Py_ssize_t i, n; if (o == NULL || !PyDict_Check(o)) { PyErr_BadInternalCall(); return NULL; } + mp = (PyDictObject *)o; + if (_PyDict_HasSplitTable(mp)) { + PyDictObject *split_copy; + PyObject **newvalues = new_values(DK_SIZE(mp->ma_keys)); + if (newvalues == NULL) + return PyErr_NoMemory(); + split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type); + if (split_copy == NULL) { + free_values(newvalues); + return NULL; + } + split_copy->ma_values = newvalues; + split_copy->ma_keys = mp->ma_keys; + split_copy->ma_used = mp->ma_used; + DK_INCREF(mp->ma_keys); + for (i = 0, n = DK_SIZE(mp->ma_keys); i < n; i++) { + PyObject *value = mp->ma_values[i]; + Py_XINCREF(value); + split_copy->ma_values[i] = value; + } + return (PyObject *)split_copy; + } copy = PyDict_New(); if (copy == NULL) return NULL; @@ -1714,14 +2081,18 @@ if (a->ma_used != b->ma_used) /* can't be equal if # of entries differ */ return 0; - /* Same # of entries -- check all of 'em. Exit early on any diff. */ - for (i = 0; i <= a->ma_mask; i++) { - PyObject *aval = a->ma_table[i].me_value; + for (i = 0; i < DK_SIZE(a->ma_keys); i++) { + PyDictKeyEntry *ep = &a->ma_keys->dk_entries[i]; + PyObject *aval; + if (a->ma_values) + aval = a->ma_values[i]; + else + aval = ep->me_value; if (aval != NULL) { int cmp; PyObject *bval; - PyObject *key = a->ma_table[i].me_key; + PyObject *key = ep->me_key; /* temporarily bump aval's refcount to ensure it stays alive until we're done with it */ Py_INCREF(aval); @@ -1742,7 +2113,7 @@ } } return 1; - } +} static PyObject * dict_richcompare(PyObject *v, PyObject *w, int op) @@ -1763,13 +2134,14 @@ res = Py_NotImplemented; Py_INCREF(res); return res; - } +} static PyObject * dict_contains(register PyDictObject *mp, PyObject *key) { Py_hash_t hash; - PyDictEntry *ep; + PyDictKeyEntry *ep; + PyObject **value_addr; if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *) key)->hash) == -1) { @@ -1777,10 +2149,10 @@ if (hash == -1) return NULL; } - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) return NULL; - return PyBool_FromLong(ep->me_value != NULL); + return PyBool_FromLong(*value_addr != NULL); } static PyObject * @@ -1790,7 +2162,8 @@ PyObject *failobj = Py_None; PyObject *val = NULL; Py_hash_t hash; - PyDictEntry *ep; + PyDictKeyEntry *ep; + PyObject **value_addr; if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj)) return NULL; @@ -1801,17 +2174,16 @@ if (hash == -1) return NULL; } - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) return NULL; - val = ep->me_value; + val = *value_addr; if (val == NULL) val = failobj; Py_INCREF(val); return val; } - static PyObject * dict_setdefault(register PyDictObject *mp, PyObject *args) { @@ -1819,7 +2191,8 @@ PyObject *failobj = Py_None; PyObject *val = NULL; Py_hash_t hash; - PyDictEntry *ep; + PyDictKeyEntry *ep; + PyObject **value_addr; if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj)) return NULL; @@ -1830,16 +2203,27 @@ if (hash == -1) return NULL; } - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) return NULL; - val = ep->me_value; + val = *value_addr; if (val == NULL) { - if (dict_set_item_by_hash_or_entry((PyObject*)mp, key, hash, ep, - failobj) == 0) - val = failobj; + Py_INCREF(failobj); + Py_INCREF(key); + if (mp->ma_keys->dk_usable <= 0) { + /* Need to resize. */ + if (insertion_resize(mp) < 0) + return NULL; + ep = find_empty_slot(mp, key, hash, &value_addr); + } + ep->me_key = key; + ep->me_hash = hash; + *value_addr = failobj; + val = failobj; + mp->ma_keys->dk_usable--; + mp->ma_used++; } - Py_XINCREF(val); + Py_INCREF(val); return val; } @@ -1855,9 +2239,10 @@ dict_pop(PyDictObject *mp, PyObject *args) { Py_hash_t hash; - PyDictEntry *ep; PyObject *old_value, *old_key; PyObject *key, *deflt = NULL; + PyDictKeyEntry *ep; + PyObject **value_addr; if(!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &deflt)) return NULL; @@ -1875,10 +2260,11 @@ if (hash == -1) return NULL; } - ep = (mp->ma_lookup)(mp, key, hash); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) return NULL; - if (ep->me_value == NULL) { + old_value = *value_addr; + if (old_value == NULL) { if (deflt) { Py_INCREF(deflt); return deflt; @@ -1886,13 +2272,15 @@ set_key_error(key); return NULL; } - old_key = ep->me_key; - Py_INCREF(dummy); - ep->me_key = dummy; - old_value = ep->me_value; - ep->me_value = NULL; + *value_addr = NULL; mp->ma_used--; - Py_DECREF(old_key); + if (!_PyDict_HasSplitTable(mp)) { + ENSURE_ALLOWS_DELETIONS(mp); + old_key = ep->me_key; + Py_INCREF(dummy); + ep->me_key = dummy; + Py_DECREF(old_key); + } return old_value; } @@ -1900,9 +2288,10 @@ dict_popitem(PyDictObject *mp) { Py_hash_t i = 0; - PyDictEntry *ep; + PyDictKeyEntry *ep; PyObject *res; + /* Allocate the result tuple before checking the size. Believe it * or not, this allocation could trigger a garbage collection which * could empty the dict, so if we checked the size first and that @@ -1921,25 +2310,34 @@ "popitem(): dictionary is empty"); return NULL; } + /* Convert split table to combined table */ + if (mp->ma_keys->dk_lookup == lookdict_split) { + if (dictresize(mp, DK_SIZE(mp->ma_keys))) { + Py_DECREF(res); + return NULL; + } + } + ENSURE_ALLOWS_DELETIONS(mp); /* Set ep to "the first" dict entry with a value. We abuse the hash * field of slot 0 to hold a search finger: * If slot 0 has a value, use slot 0. * Else slot 0 is being used to hold a search finger, * and we use its hash value as the first index to look. */ - ep = &mp->ma_table[0]; + ep = &mp->ma_keys->dk_entries[0]; if (ep->me_value == NULL) { + Py_ssize_t mask = DK_MASK(mp->ma_keys); i = ep->me_hash; /* The hash field may be a real hash value, or it may be a * legit search finger, or it may be a once-legit search * finger that's out of bounds now because it wrapped around * or the table shrunk -- simply make sure it's in bounds now. */ - if (i > mp->ma_mask || i < 1) + if (i > mask || i < 1) i = 1; /* skip slot 0 */ - while ((ep = &mp->ma_table[i])->me_value == NULL) { + while ((ep = &mp->ma_keys->dk_entries[i])->me_value == NULL) { i++; - if (i > mp->ma_mask) + if (i > mask) i = 1; } } @@ -1949,21 +2347,34 @@ ep->me_key = dummy; ep->me_value = NULL; mp->ma_used--; - assert(mp->ma_table[0].me_value == NULL); - mp->ma_table[0].me_hash = i + 1; /* next place to start */ + assert(mp->ma_keys->dk_entries[0].me_value == NULL); + mp->ma_keys->dk_entries[0].me_hash = i + 1; /* next place to start */ return res; } static int dict_traverse(PyObject *op, visitproc visit, void *arg) { - Py_ssize_t i = 0; - PyObject *pk; - PyObject *pv; - - while (PyDict_Next(op, &i, &pk, &pv)) { - Py_VISIT(pk); - Py_VISIT(pv); + Py_ssize_t i, n; + PyDictObject *mp = (PyDictObject *)op; + if (mp->ma_keys->dk_lookup == lookdict) { + for (i = 0; i < DK_SIZE(mp->ma_keys); i++) { + if (mp->ma_keys->dk_entries[i].me_value != NULL) { + Py_VISIT(mp->ma_keys->dk_entries[i].me_value); + Py_VISIT(mp->ma_keys->dk_entries[i].me_key); + } + } + } else { + if (mp->ma_values != NULL) { + for (i = 0, n = DK_SIZE(mp->ma_keys); i < n; i++) { + Py_VISIT(mp->ma_values[i]); + } + } + else { + for (i = 0, n = DK_SIZE(mp->ma_keys); i < n; i++) { + Py_VISIT(mp->ma_keys->dk_entries[i].me_value); + } + } } return 0; } @@ -1980,12 +2391,22 @@ static PyObject * dict_sizeof(PyDictObject *mp) { - Py_ssize_t res; - + Py_ssize_t size; + double res, keys_size; + + size = DK_SIZE(mp->ma_keys); res = sizeof(PyDictObject); - if (mp->ma_table != mp->ma_smalltable) - res = res + (mp->ma_mask + 1) * sizeof(PyDictEntry); - return PyLong_FromSsize_t(res); + if (mp->ma_values) + res += size * sizeof(PyObject*); + /* Count our share of the keys object -- with rounding errors. */ + keys_size = sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry); + /* If refcnt > 1, then one count is (probably) held by a type */ + /* XXX This is somewhat approximate :) */ + if (mp->ma_keys->dk_refcnt < 3) + res += keys_size; + else + res += keys_size / (mp->ma_keys->dk_refcnt - 1); + return PyFloat_FromDouble(res); } PyDoc_STRVAR(contains__doc__, @@ -2076,7 +2497,8 @@ { Py_hash_t hash; PyDictObject *mp = (PyDictObject *)op; - PyDictEntry *ep; + PyDictKeyEntry *ep; + PyObject **value_addr; if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *) key)->hash) == -1) { @@ -2084,8 +2506,8 @@ if (hash == -1) return -1; } - ep = (mp->ma_lookup)(mp, key, hash); - return ep == NULL ? -1 : (ep->me_value != NULL); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); + return (ep == NULL) ? -1 : (*value_addr != NULL); } /* Internal version of PyDict_Contains used when the hash value is already known */ @@ -2093,10 +2515,11 @@ _PyDict_Contains(PyObject *op, PyObject *key, Py_hash_t hash) { PyDictObject *mp = (PyDictObject *)op; - PyDictEntry *ep; - - ep = (mp->ma_lookup)(mp, key, hash); - return ep == NULL ? -1 : (ep->me_value != NULL); + PyDictKeyEntry *ep; + PyObject **value_addr; + + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); + return (ep == NULL) ? -1 : (*value_addr != NULL); } /* Hack to implement "key in dict" */ @@ -2122,22 +2545,17 @@ self = type->tp_alloc(type, 0); if (self != NULL) { PyDictObject *d = (PyDictObject *)self; - /* It's guaranteed that tp->alloc zeroed out the struct. */ - assert(d->ma_table == NULL && d->ma_fill == 0 && d->ma_used == 0); - INIT_NONZERO_DICT_SLOTS(d); - d->ma_lookup = lookdict_unicode; + d->ma_keys = new_keys_object(PyDict_MINSIZE_COMBINED); + /* XXX - Should we raise a no-memory error? */ + if (d->ma_keys == NULL) { + DK_INCREF(Py_EMPTY_KEYS); + d->ma_keys = Py_EMPTY_KEYS; + d->ma_values = empty_values; + } + d->ma_used = 0; /* The object has been implicitly tracked by tp_alloc */ if (type == &PyDict_Type) _PyObject_GC_UNTRACK(d); -#ifdef SHOW_CONVERSION_COUNTS - ++created; -#endif -#ifdef SHOW_TRACK_COUNT - if (_PyObject_GC_IS_TRACKED(d)) - count_tracked++; - else - count_untracked++; -#endif } return self; } @@ -2349,9 +2767,10 @@ static PyObject *dictiter_iternextkey(dictiterobject *di) { PyObject *key; - register Py_ssize_t i, mask; - register PyDictEntry *ep; + register Py_ssize_t i, mask, offset; + register PyDictKeysObject *k; PyDictObject *d = di->di_dict; + PyObject **value_ptr; if (d == NULL) return NULL; @@ -2367,15 +2786,25 @@ i = di->di_pos; if (i < 0) goto fail; - ep = d->ma_table; - mask = d->ma_mask; - while (i <= mask && ep[i].me_value == NULL) + k = d->ma_keys; + if (d->ma_values) { + value_ptr = &d->ma_values[i]; + offset = sizeof(PyObject *); + } + else { + value_ptr = &k->dk_entries[i].me_value; + offset = sizeof(PyDictKeyEntry); + } + mask = DK_SIZE(k)-1; + while (i <= mask && *value_ptr == NULL) { + value_ptr = (PyObject **)(((char *)value_ptr) + offset); i++; + } di->di_pos = i+1; if (i > mask) goto fail; di->len--; - key = ep[i].me_key; + key = k->dk_entries[i].me_key; Py_INCREF(key); return key; @@ -2421,9 +2850,9 @@ static PyObject *dictiter_iternextvalue(dictiterobject *di) { PyObject *value; - register Py_ssize_t i, mask; - register PyDictEntry *ep; + register Py_ssize_t i, mask, offset; PyDictObject *d = di->di_dict; + PyObject **value_ptr; if (d == NULL) return NULL; @@ -2437,17 +2866,26 @@ } i = di->di_pos; - mask = d->ma_mask; + mask = DK_SIZE(d->ma_keys)-1; if (i < 0 || i > mask) goto fail; - ep = d->ma_table; - while ((value=ep[i].me_value) == NULL) { + if (d->ma_values) { + value_ptr = &d->ma_values[i]; + offset = sizeof(PyObject *); + } + else { + value_ptr = &d->ma_keys->dk_entries[i].me_value; + offset = sizeof(PyDictKeyEntry); + } + while (i <= mask && *value_ptr == NULL) { + value_ptr = (PyObject **)(((char *)value_ptr) + offset); i++; if (i > mask) goto fail; } di->di_pos = i+1; di->len--; + value = *value_ptr; Py_INCREF(value); return value; @@ -2493,9 +2931,9 @@ static PyObject *dictiter_iternextitem(dictiterobject *di) { PyObject *key, *value, *result = di->di_result; - register Py_ssize_t i, mask; - register PyDictEntry *ep; + register Py_ssize_t i, mask, offset; PyDictObject *d = di->di_dict; + PyObject **value_ptr; if (d == NULL) return NULL; @@ -2511,10 +2949,19 @@ i = di->di_pos; if (i < 0) goto fail; - ep = d->ma_table; - mask = d->ma_mask; - while (i <= mask && ep[i].me_value == NULL) + mask = DK_SIZE(d->ma_keys)-1; + if (d->ma_values) { + value_ptr = &d->ma_values[i]; + offset = sizeof(PyObject *); + } + else { + value_ptr = &d->ma_keys->dk_entries[i].me_value; + offset = sizeof(PyDictKeyEntry); + } + while (i <= mask && *value_ptr == NULL) { + value_ptr = (PyObject **)(((char *)value_ptr) + offset); i++; + } di->di_pos = i+1; if (i > mask) goto fail; @@ -2529,8 +2976,8 @@ return NULL; } di->len--; - key = ep[i].me_key; - value = ep[i].me_value; + key = d->ma_keys->dk_entries[i].me_key; + value = *value_ptr; Py_INCREF(key); Py_INCREF(value); PyTuple_SET_ITEM(result, 0, key); @@ -2590,7 +3037,7 @@ /* copy the itertor state */ tmp = *di; Py_XINCREF(tmp.di_dict); - + /* iterate the temporary into a list */ for(;;) { PyObject *element = 0; @@ -3170,3 +3617,151 @@ { return dictview_new(dict, &PyDictValues_Type); } + +/* Returns NULL if cannot allocate a new PyDictKeysObject, + but does not set an error */ +PyDictKeysObject * +_PyDict_NewKeysForClass(void) +{ + PyDictKeysObject *keys = new_keys_object(PyDict_MINSIZE_SPLIT); + if (keys == NULL) + PyErr_Clear(); + else + keys->dk_lookup = lookdict_split; + return keys; +} + +#define CACHED_KEYS(tp) (((PyHeapTypeObject*)tp)->ht_cached_keys) + +PyObject * +PyObject_GenericGetDict(PyObject *obj, void *context) +{ + PyObject *dict, **dictptr = _PyObject_GetDictPtr(obj); + if (dictptr == NULL) { + PyErr_SetString(PyExc_AttributeError, + "This object has no __dict__"); + return NULL; + } + dict = *dictptr; + if (dict == NULL) { + PyTypeObject *tp = Py_TYPE(obj); + if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) { + DK_INCREF(CACHED_KEYS(tp)); + *dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp)); + } + else { + *dictptr = dict = PyDict_New(); + } + } + Py_XINCREF(dict); + return dict; +} + +int +_PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, + PyObject *key, PyObject *value) +{ + PyObject *dict; + int res; + PyDictKeysObject *cached; + + assert(dictptr != NULL); + if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) { + assert(dictptr != NULL); + dict = *dictptr; + if (dict == NULL) { + DK_INCREF(cached); + dict = new_dict_with_shared_keys(cached); + if (dict == NULL) + return -1; + *dictptr = dict; + } + if (value == NULL) { + res = PyDict_DelItem(dict, key); + if (cached != ((PyDictObject *)dict)->ma_keys) { + CACHED_KEYS(tp) = NULL; + DK_DECREF(cached); + } + } else { + res = PyDict_SetItem(dict, key, value); + if (cached != ((PyDictObject *)dict)->ma_keys) { + /* Either update tp->ht_cached_keys or delete it */ + if (cached->dk_refcnt == 1) { + CACHED_KEYS(tp) = make_keys_shared(dict); + if (CACHED_KEYS(tp) == NULL) + return -1; + } else { + CACHED_KEYS(tp) = NULL; + } + DK_DECREF(cached); + } + } + } else { + dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + if (dict == NULL) + return -1; + *dictptr = dict; + } + if (value == NULL) { + res = PyDict_DelItem(dict, key); + } else { + res = PyDict_SetItem(dict, key, value); + } + } + return res; +} + +void +_PyDictKeys_DecRef(PyDictKeysObject *keys) +{ + DK_DECREF(keys); +} + + +/* ARGSUSED */ +static PyObject * +dummy_repr(PyObject *op) +{ + return PyUnicode_FromString(""); +} + +/* ARGUSED */ +static void +dummy_dealloc(PyObject* ignore) +{ + /* This should never get called, but we also don't want to SEGV if + * we accidentally decref dummy-key out of existence. + */ + Py_FatalError("deallocating "); +} + +static PyTypeObject PyDictDummy_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + " type", + 0, + 0, + dummy_dealloc, /*tp_dealloc*/ /*never called*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_reserved*/ + dummy_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call */ + 0, /*tp_str */ + 0, /*tp_getattro */ + 0, /*tp_setattro */ + 0, /*tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /*tp_flags */ +}; + +static PyObject _dummy_struct = { + _PyObject_EXTRA_INIT + 2, &PyDictDummy_Type +}; + diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1188,13 +1188,10 @@ if (dict == NULL) { dictptr = _PyObject_GetDictPtr(obj); if (dictptr != NULL) { - dict = *dictptr; - if (dict == NULL && value != NULL) { - dict = PyDict_New(); - if (dict == NULL) - goto done; - *dictptr = dict; - } + res = _PyObjectDict_SetItem(Py_TYPE(obj), dictptr, name, value); + if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) + PyErr_SetObject(PyExc_AttributeError, name); + goto done; } } if (dict != NULL) { @@ -1236,22 +1233,6 @@ return _PyObject_GenericSetAttrWithDict(obj, name, value, NULL); } -PyObject * -PyObject_GenericGetDict(PyObject *obj, void *context) -{ - PyObject *dict, **dictptr = _PyObject_GetDictPtr(obj); - if (dictptr == NULL) { - PyErr_SetString(PyExc_AttributeError, - "This object has no __dict__"); - return NULL; - } - dict = *dictptr; - if (dict == NULL) - *dictptr = dict = PyDict_New(); - Py_XINCREF(dict); - return dict; -} - int PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context) { diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -14,7 +14,7 @@ MCACHE_MAX_ATTR_SIZE, since it might be a problem if very large strings are used as attribute names. */ #define MCACHE_MAX_ATTR_SIZE 100 -#define MCACHE_SIZE_EXP 10 +#define MCACHE_SIZE_EXP 9 #define MCACHE_HASH(version, name_hash) \ (((unsigned int)(version) * (unsigned int)(name_hash)) \ >> (8*sizeof(unsigned int) - MCACHE_SIZE_EXP)) @@ -2306,6 +2306,9 @@ type->tp_dictoffset = slotoffset; slotoffset += sizeof(PyObject *); } + if (type->tp_dictoffset) { + et->ht_cached_keys = _PyDict_NewKeysForClass(); + } if (add_weak) { assert(!base->tp_itemsize); type->tp_weaklistoffset = slotoffset; @@ -2411,6 +2414,9 @@ res->ht_type.tp_doc = tp_doc; } } + if (res->ht_type.tp_dictoffset) { + res->ht_cached_keys = _PyDict_NewKeysForClass(); + } if (PyType_Ready(&res->ht_type) < 0) goto fail; @@ -2767,9 +2773,13 @@ return 0; } +extern void +_PyDictKeys_DecRef(PyDictKeysObject *keys); + static int type_clear(PyTypeObject *type) { + PyDictKeysObject *cached_keys; /* Because of type_is_gc(), the collector only calls this for heaptypes. */ assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); @@ -2801,6 +2811,11 @@ */ PyType_Modified(type); + cached_keys = ((PyHeapTypeObject *)type)->ht_cached_keys; + if (cached_keys != NULL) { + ((PyHeapTypeObject *)type)->ht_cached_keys = NULL; + _PyDictKeys_DecRef(cached_keys); + } if (type->tp_dict) PyDict_Clear(type->tp_dict); Py_CLEAR(type->tp_mro); diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2123,70 +2123,31 @@ w = GETITEM(names, oparg); if (PyDict_CheckExact(f->f_globals) && PyDict_CheckExact(f->f_builtins)) { - if (PyUnicode_CheckExact(w)) { - /* Inline the PyDict_GetItem() calls. - WARNING: this is an extreme speed hack. - Do not try this at home. */ - Py_hash_t hash = ((PyASCIIObject *)w)->hash; - if (hash != -1) { - PyDictObject *d; - PyDictEntry *e; - d = (PyDictObject *)(f->f_globals); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - d = (PyDictObject *)(f->f_builtins); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - goto load_global_error; - } + x = _PyDict_LoadGlobal((PyDictObject *)f->f_globals, + (PyDictObject *)f->f_builtins, + w); + if (x == NULL) { + if (!PyErr_Occurred()) + format_exc_check_arg(PyExc_NameError, + GLOBAL_NAME_ERROR_MSG, w); + break; } - /* This is the un-inlined version of the code above */ - x = PyDict_GetItem(f->f_globals, w); + } + else { + /* Slow-path if globals or builtins is not a dict */ + x = PyObject_GetItem(f->f_globals, w); if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); + x = PyObject_GetItem(f->f_builtins, w); if (x == NULL) { - load_global_error: - format_exc_check_arg( - PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, w); + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + GLOBAL_NAME_ERROR_MSG, w); break; } } - Py_INCREF(x); - PUSH(x); - DISPATCH(); } - - /* Slow-path if globals or builtins is not a dict */ - x = PyObject_GetItem(f->f_globals, w); - if (x == NULL) { - x = PyObject_GetItem(f->f_builtins, w); - if (x == NULL) { - if (PyErr_ExceptionMatches(PyExc_KeyError)) - format_exc_check_arg( - PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, w); - break; - } - } + Py_INCREF(x); PUSH(x); DISPATCH(); diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -634,9 +634,14 @@ Yields a sequence of (PyObjectPtr key, PyObjectPtr value) pairs, analagous to dict.iteritems() ''' - for i in safe_range(self.field('ma_mask') + 1): - ep = self.field('ma_table') + i - pyop_value = PyObjectPtr.from_pyobject_ptr(ep['me_value']) + keys = self.field('ma_keys') + values = self.field('ma_values') + for i in safe_range(keys['dk_size']): + ep = keys['dk_entries'].address + i + if long(values): + pyop_value = PyObjectPtr.from_pyobject_ptr(values[i]) + else: + pyop_value = PyObjectPtr.from_pyobject_ptr(ep['me_value']) if not pyop_value.is_null(): pyop_key = PyObjectPtr.from_pyobject_ptr(ep['me_key']) yield (pyop_key, pyop_value) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:26:05 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 17:26:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_add_Mark_Shanno?= =?utf8?q?n?= Message-ID: http://hg.python.org/cpython/rev/505828be1711 changeset: 76486:505828be1711 branch: 3.2 parent: 76481:1040e3811485 user: Benjamin Peterson date: Mon Apr 23 11:25:32 2012 -0400 summary: add Mark Shannon 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 @@ -847,6 +847,7 @@ Denis Severson Ian Seyer Ha Shao +Mark Shannon Richard Shapiro Bruce Sherwood Alexander Shigin -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:26:06 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 17:26:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_add_Mark_Shanno?= =?utf8?q?n?= Message-ID: http://hg.python.org/cpython/rev/3c53edb86ee3 changeset: 76487:3c53edb86ee3 branch: 2.7 parent: 76483:3182453e74f9 user: Benjamin Peterson date: Mon Apr 23 11:25:32 2012 -0400 summary: add Mark Shannon 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 @@ -774,6 +774,7 @@ Denis Severson Ian Seyer Ha Shao +Mark Shannon Richard Shapiro Bruce Sherwood Alexander Shigin -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:26:07 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 17:26:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/9a84cab7ff9d changeset: 76488:9a84cab7ff9d parent: 76485:6e5855854a2e parent: 76486:505828be1711 user: Benjamin Peterson date: Mon Apr 23 11:25:49 2012 -0400 summary: merge 3.2 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 @@ -933,6 +933,7 @@ Denis Severson Ian Seyer Ha Shao +Mark Shannon Richard Shapiro Bruce Sherwood Alexander Shigin -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:28:33 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 17:28:33 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_finalize_pep_412?= Message-ID: http://hg.python.org/peps/rev/5ad47148ed20 changeset: 4295:5ad47148ed20 user: Benjamin Peterson date: Mon Apr 23 11:28:28 2012 -0400 summary: finalize pep 412 files: pep-0412.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0412.txt b/pep-0412.txt --- a/pep-0412.txt +++ b/pep-0412.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Mark Shannon -Status: Draft +Status: Final Type: Standards Track Content-Type: text/x-rst Created: 08-Feb-2012 -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 23 17:50:52 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 17:50:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_don=27t_make_shared_keys_wi?= =?utf8?q?th_dict_subclasses?= Message-ID: http://hg.python.org/cpython/rev/e3ea9e975689 changeset: 76489:e3ea9e975689 user: Benjamin Peterson date: Mon Apr 23 11:50:47 2012 -0400 summary: don't make shared keys with dict subclasses files: Objects/dictobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -3686,7 +3686,7 @@ res = PyDict_SetItem(dict, key, value); if (cached != ((PyDictObject *)dict)->ma_keys) { /* Either update tp->ht_cached_keys or delete it */ - if (cached->dk_refcnt == 1) { + if (cached->dk_refcnt == 1 && PyDict_CheckExact(dict)) { CACHED_KEYS(tp) = make_keys_shared(dict); if (CACHED_KEYS(tp) == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:57:05 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 23 Apr 2012 17:57:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A__Fix_for_Issue1?= =?utf8?q?3684_-_httplib_tunnel_infinite_loop?= Message-ID: http://hg.python.org/cpython/rev/790ae45b52be changeset: 76490:790ae45b52be branch: 2.7 parent: 76487:3c53edb86ee3 user: Senthil Kumaran date: Mon Apr 23 23:46:46 2012 +0800 summary: Fix for Issue13684 - httplib tunnel infinite loop files: Lib/httplib.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/httplib.py b/Lib/httplib.py --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -748,7 +748,11 @@ line = response.fp.readline(_MAXLINE + 1) if len(line) > _MAXLINE: raise LineTooLong("header line") - if line == '\r\n': break + if not line: + # for sites which EOF without sending trailer + break + if line == '\r\n': + break def connect(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:57:06 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 23 Apr 2012 17:57:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A__3=2E2_-_Fix_fo?= =?utf8?q?r_Issue13684_-_httplib_tunnel_infinite_loop?= Message-ID: http://hg.python.org/cpython/rev/7787a9aebdc6 changeset: 76491:7787a9aebdc6 branch: 3.2 parent: 76486:505828be1711 user: Senthil Kumaran date: Mon Apr 23 23:50:07 2012 +0800 summary: 3.2 - Fix for Issue13684 - httplib tunnel infinite loop files: Lib/http/client.py | 3 +++ 1 files changed, 3 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 @@ -715,6 +715,9 @@ line = response.fp.readline(_MAXLINE + 1) if len(line) > _MAXLINE: raise LineTooLong("header line") + if not line: + # for sites which EOF without sending a trailer + break if line == b'\r\n': break -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:57:07 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 23 Apr 2012 17:57:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_news_for_issue1?= =?utf8?q?3684?= Message-ID: http://hg.python.org/cpython/rev/f98fb46ff273 changeset: 76492:f98fb46ff273 branch: 2.7 parent: 76490:790ae45b52be user: Senthil Kumaran date: Mon Apr 23 23:52:40 2012 +0800 summary: news for issue13684 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 @@ -50,6 +50,9 @@ Library ------- +- Issue #13684: Fix httplib tunnel issue of infinite loops for certain sites + which send EOF without trailing \r\n. + - Issue #14308: Fix an exception when a "dummy" thread is in the threading module's active list after a fork(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:57:08 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 23 Apr 2012 17:57:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_news_for_issue1?= =?utf8?q?3684?= Message-ID: http://hg.python.org/cpython/rev/26631c56d81f changeset: 76493:26631c56d81f branch: 3.2 parent: 76491:7787a9aebdc6 user: Senthil Kumaran date: Mon Apr 23 23:53:16 2012 +0800 summary: news for issue13684 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 @@ -50,6 +50,9 @@ Library ------- +- Issue #13684: Fix httplib tunnel issue of infinite loops for certain sites + which send EOF without trailing \r\n. + - Issue #14629: Raise SyntaxError in tokenizer.detect_encoding if the first two lines have non-UTF-8 characters without an encoding declaration. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:57:08 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 23 Apr 2012 17:57:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A__3=2E2_-_Fix_for_Issue13684_-_httplib_tunnel_infinite_loop?= Message-ID: http://hg.python.org/cpython/rev/1acb252a3858 changeset: 76494:1acb252a3858 parent: 76488:9a84cab7ff9d parent: 76491:7787a9aebdc6 user: Senthil Kumaran date: Mon Apr 23 23:53:51 2012 +0800 summary: 3.2 - Fix for Issue13684 - httplib tunnel infinite loop files: Lib/http/client.py | 3 +++ 1 files changed, 3 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 @@ -786,6 +786,9 @@ line = response.fp.readline(_MAXLINE + 1) if len(line) > _MAXLINE: raise LineTooLong("header line") + if not line: + # for sites which EOF without sending a trailer + break if line == b'\r\n': break -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:57:09 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 23 Apr 2012 17:57:09 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_news_for_issue13684?= Message-ID: http://hg.python.org/cpython/rev/246abd64e830 changeset: 76495:246abd64e830 parent: 76494:1acb252a3858 parent: 76493:26631c56d81f user: Senthil Kumaran date: Mon Apr 23 23:55:50 2012 +0800 summary: news for issue13684 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 @@ -65,6 +65,9 @@ Library ------- +- Issue #13684: Fix httplib tunnel issue of infinite loops for certain sites + which send EOF without trailing \r\n. + - Issue #14605: Add importlib.abc.FileLoader, importlib.machinery.(FileFinder, SourceFileLoader, _SourcelessFileLoader, ExtensionFileLoader). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 17:57:10 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 23 Apr 2012 17:57:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/55c951167cd9 changeset: 76496:55c951167cd9 parent: 76495:246abd64e830 parent: 76489:e3ea9e975689 user: Senthil Kumaran date: Mon Apr 23 23:56:36 2012 +0800 summary: merge heads files: Objects/dictobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -3686,7 +3686,7 @@ res = PyDict_SetItem(dict, key, value); if (cached != ((PyDictObject *)dict)->ma_keys) { /* Either update tp->ht_cached_keys or delete it */ - if (cached->dk_refcnt == 1) { + if (cached->dk_refcnt == 1 && PyDict_CheckExact(dict)) { CACHED_KEYS(tp) = make_keys_shared(dict); if (CACHED_KEYS(tp) == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 19:27:50 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 23 Apr 2012 19:27:50 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NjM4OiBweWRv?= =?utf8?q?c_now_treats_non-str_=5F=5Fname=5F=5F_as_None_instead_of_raising?= Message-ID: http://hg.python.org/cpython/rev/2a35dfbe3d99 changeset: 76497:2a35dfbe3d99 branch: 3.2 parent: 76493:26631c56d81f user: R David Murray date: Mon Apr 23 13:23:57 2012 -0400 summary: #14638: pydoc now treats non-str __name__ as None instead of raising Original patch by Peter Otten. files: Lib/pydoc.py | 3 ++- Lib/test/test_pydoc.py | 11 +++++++++++ Misc/NEWS | 3 +++ 3 files changed, 16 insertions(+), 1 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1525,7 +1525,8 @@ raise ImportError('no Python documentation found for %r' % thing) return object, thing else: - return thing, getattr(thing, '__name__', None) + name = getattr(thing, '__name__', None) + return thing, name if isinstance(name, str) else None def render_doc(thing, title='Python Library Documentation: %s', forceload=0, renderer=None): 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 @@ -282,6 +282,17 @@ result, doc_loc = get_pydoc_text(xml.etree) self.assertEqual(doc_loc, "", "MODULE DOCS incorrectly includes a link") + def test_non_str_name(self): + # issue14638 + # Treat illegal (non-str) name like no name + class A: + __name__ = 42 + class B: + pass + adoc = pydoc.render_doc(A()) + bdoc = pydoc.render_doc(B()) + self.assertEqual(adoc.replace("A", "B"), bdoc) + def test_not_here(self): missing_module = "test.i_am_not_here" result = str(run_pydoc(missing_module), 'ascii') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Library ------- +- Issue #14638: pydoc now treats non-string __name__ values as if they + were missing, instead of raising an error. + - Issue #13684: Fix httplib tunnel issue of infinite loops for certain sites which send EOF without trailing \r\n. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 19:27:51 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 23 Apr 2012 19:27:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merge_=2314638=3A_pydoc_now_treats_non-str_=5F=5Fname=5F=5F_?= =?utf8?q?as_None_instead_of_raising?= Message-ID: http://hg.python.org/cpython/rev/86b4b54bb0fa changeset: 76498:86b4b54bb0fa parent: 76496:55c951167cd9 parent: 76497:2a35dfbe3d99 user: R David Murray date: Mon Apr 23 13:26:44 2012 -0400 summary: merge #14638: pydoc now treats non-str __name__ as None instead of raising Original patch by Peter Otten. files: Lib/pydoc.py | 3 ++- Lib/test/test_pydoc.py | 11 +++++++++++ Misc/NEWS | 3 +++ 3 files changed, 16 insertions(+), 1 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1521,7 +1521,8 @@ raise ImportError('no Python documentation found for %r' % thing) return object, thing else: - return thing, getattr(thing, '__name__', None) + name = getattr(thing, '__name__', None) + return thing, name if isinstance(name, str) else None def render_doc(thing, title='Python Library Documentation: %s', forceload=0, renderer=None): 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 @@ -286,6 +286,17 @@ result, doc_loc = get_pydoc_text(xml.etree) self.assertEqual(doc_loc, "", "MODULE DOCS incorrectly includes a link") + def test_non_str_name(self): + # issue14638 + # Treat illegal (non-str) name like no name + class A: + __name__ = 42 + class B: + pass + adoc = pydoc.render_doc(A()) + bdoc = pydoc.render_doc(B()) + self.assertEqual(adoc.replace("A", "B"), bdoc) + def test_not_here(self): missing_module = "test.i_am_not_here" result = str(run_pydoc(missing_module), 'ascii') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -65,6 +65,9 @@ Library ------- +- Issue #14638: pydoc now treats non-string __name__ values as if they + were missing, instead of raising an error. + - Issue #13684: Fix httplib tunnel issue of infinite loops for certain sites which send EOF without trailing \r\n. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 19:27:53 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 23 Apr 2012 19:27:53 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0NjM4OiBweWRv?= =?utf8?q?c_now_treats_non-str_=5F=5Fname=5F=5F_as_None_instead_of_raising?= Message-ID: http://hg.python.org/cpython/rev/501651b93cb0 changeset: 76499:501651b93cb0 branch: 2.7 parent: 76492:f98fb46ff273 user: R David Murray date: Mon Apr 23 13:27:11 2012 -0400 summary: #14638: pydoc now treats non-str __name__ as None instead of raising Original patch by Peter Otten. files: Lib/pydoc.py | 3 ++- Lib/test/test_pydoc.py | 11 +++++++++++ Misc/NEWS | 3 +++ 3 files changed, 16 insertions(+), 1 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1498,7 +1498,8 @@ raise ImportError, 'no Python documentation found for %r' % thing return object, thing else: - return thing, getattr(thing, '__name__', None) + name = getattr(thing, '__name__', None) + return thing, name if isinstance(name, str) else None def render_doc(thing, title='Python Library Documentation: %s', forceload=0): """Render text documentation, given an object or a path to an object.""" 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 @@ -249,6 +249,17 @@ result, doc_loc = get_pydoc_text(xml.etree) self.assertEqual(doc_loc, "", "MODULE DOCS incorrectly includes a link") + def test_non_str_name(self): + # issue14638 + # Treat illegal (non-str) name like no name + class A: + __name__ = 42 + class B: + pass + adoc = pydoc.render_doc(A()) + bdoc = pydoc.render_doc(B()) + self.assertEqual(adoc.replace("A", "B"), bdoc) + def test_not_here(self): missing_module = "test.i_am_not_here" result = run_pydoc(missing_module) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Library ------- +- Issue #14638: pydoc now treats non-string __name__ values as if they + were missing, instead of raising an error. + - Issue #13684: Fix httplib tunnel issue of infinite loops for certain sites which send EOF without trailing \r\n. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 19:47:23 2012 From: python-checkins at python.org (sandro.tosi) Date: Mon, 23 Apr 2012 19:47:23 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NjQx?= =?utf8?q?=3A_minor_fixes_to_sockets_Howto=3B_patch_by_Dionysios_Kalofonos?= Message-ID: http://hg.python.org/cpython/rev/f24d8dc1a986 changeset: 76500:f24d8dc1a986 branch: 2.7 user: Sandro Tosi date: Mon Apr 23 19:44:51 2012 +0200 summary: Issue #14641: minor fixes to sockets Howto; patch by Dionysios Kalofonos files: Doc/howto/sockets.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -156,7 +156,7 @@ there, you may wait forever for the reply, because the request may still be in your output buffer. -Now we come the major stumbling block of sockets - ``send`` and ``recv`` operate +Now we come to the major stumbling block of sockets - ``send`` and ``recv`` operate on the network buffers. They do not necessarily handle all the bytes you hand them (or expect from them), because their major focus is handling the network buffers. In general, they return when the associated network buffers have been @@ -167,7 +167,7 @@ When a ``recv`` returns 0 bytes, it means the other side has closed (or is in the process of closing) the connection. You will not receive any more data on this connection. Ever. You may be able to send data successfully; I'll talk -about that some on the next page. +more about this later. A protocol like HTTP uses a socket for only one transfer. The client sends a request, then reads a reply. That's it. The socket is discarded. This means that -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 19:47:24 2012 From: python-checkins at python.org (sandro.tosi) Date: Mon, 23 Apr 2012 19:47:24 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NjQx?= =?utf8?q?=3A_minor_fixes_to_sockets_Howto=3B_patch_by_Dionysios_Kalofonos?= Message-ID: http://hg.python.org/cpython/rev/9bb9604519ce changeset: 76501:9bb9604519ce branch: 3.2 parent: 76497:2a35dfbe3d99 user: Sandro Tosi date: Mon Apr 23 19:45:07 2012 +0200 summary: Issue #14641: minor fixes to sockets Howto; patch by Dionysios Kalofonos files: Doc/howto/sockets.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -153,7 +153,7 @@ there, you may wait forever for the reply, because the request may still be in your output buffer. -Now we come the major stumbling block of sockets - ``send`` and ``recv`` operate +Now we come to the major stumbling block of sockets - ``send`` and ``recv`` operate on the network buffers. They do not necessarily handle all the bytes you hand them (or expect from them), because their major focus is handling the network buffers. In general, they return when the associated network buffers have been @@ -164,7 +164,7 @@ When a ``recv`` returns 0 bytes, it means the other side has closed (or is in the process of closing) the connection. You will not receive any more data on this connection. Ever. You may be able to send data successfully; I'll talk -about that some on the next page. +more about this later. A protocol like HTTP uses a socket for only one transfer. The client sends a request, then reads a reply. That's it. The socket is discarded. This means that -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 19:47:25 2012 From: python-checkins at python.org (sandro.tosi) Date: Mon, 23 Apr 2012 19:47:25 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314641=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/caf39de79819 changeset: 76502:caf39de79819 parent: 76498:86b4b54bb0fa parent: 76501:9bb9604519ce user: Sandro Tosi date: Mon Apr 23 19:45:45 2012 +0200 summary: Issue #14641: merge with 3.2 files: Doc/howto/sockets.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -153,7 +153,7 @@ there, you may wait forever for the reply, because the request may still be in your output buffer. -Now we come the major stumbling block of sockets - ``send`` and ``recv`` operate +Now we come to the major stumbling block of sockets - ``send`` and ``recv`` operate on the network buffers. They do not necessarily handle all the bytes you hand them (or expect from them), because their major focus is handling the network buffers. In general, they return when the associated network buffers have been @@ -164,7 +164,7 @@ When a ``recv`` returns 0 bytes, it means the other side has closed (or is in the process of closing) the connection. You will not receive any more data on this connection. Ever. You may be able to send data successfully; I'll talk -about that some on the next page. +more about this later. A protocol like HTTP uses a socket for only one transfer. The client sends a request, then reads a reply. That's it. The socket is discarded. This means that -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 19:50:13 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 19:50:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_fix_instance_dicts_with_str?= =?utf8?q?_subclasses_=28=2313903=29?= Message-ID: http://hg.python.org/cpython/rev/34b6998efd2c changeset: 76503:34b6998efd2c parent: 76489:e3ea9e975689 user: Benjamin Peterson date: Mon Apr 23 13:44:32 2012 -0400 summary: fix instance dicts with str subclasses (#13903) files: Lib/test/test_dict.py | 10 ++++++++++ Objects/dictobject.c | 6 +++++- 2 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -879,6 +879,16 @@ values = list(it) + [drop] self.assertEqual(sorted(values), sorted(list(data.values()))) + def test_instance_dict_getattr_str_subclass(self): + class Foo: + def __init__(self, msg): + self.msg = msg + f = Foo('123') + class _str(str): + pass + self.assertEqual(f.msg, getattr(f, _str('msg'))) + self.assertEqual(f.msg, f.__dict__[_str('msg')]) + from test import mapping_tests class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -641,7 +641,11 @@ register PyDictKeyEntry *ep; if (!PyUnicode_CheckExact(key)) { - return lookdict(mp, key, hash, value_addr); + ep = lookdict(mp, key, hash, value_addr); + /* lookdict expects a combined-table, so fix value_addr */ + i = ep - ep0; + *value_addr = &mp->ma_values[i]; + return ep; } i = (size_t)hash & mask; ep = &ep0[i]; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 19:50:14 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Apr 2012 19:50:14 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/a876bee0fc64 changeset: 76504:a876bee0fc64 parent: 76503:34b6998efd2c parent: 76502:caf39de79819 user: Benjamin Peterson date: Mon Apr 23 13:50:05 2012 -0400 summary: merge heads files: Doc/howto/sockets.rst | 4 ++-- Lib/http/client.py | 3 +++ Lib/pydoc.py | 3 ++- Lib/test/test_pydoc.py | 11 +++++++++++ Misc/NEWS | 6 ++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -153,7 +153,7 @@ there, you may wait forever for the reply, because the request may still be in your output buffer. -Now we come the major stumbling block of sockets - ``send`` and ``recv`` operate +Now we come to the major stumbling block of sockets - ``send`` and ``recv`` operate on the network buffers. They do not necessarily handle all the bytes you hand them (or expect from them), because their major focus is handling the network buffers. In general, they return when the associated network buffers have been @@ -164,7 +164,7 @@ When a ``recv`` returns 0 bytes, it means the other side has closed (or is in the process of closing) the connection. You will not receive any more data on this connection. Ever. You may be able to send data successfully; I'll talk -about that some on the next page. +more about this later. A protocol like HTTP uses a socket for only one transfer. The client sends a request, then reads a reply. That's it. The socket is discarded. This means that diff --git a/Lib/http/client.py b/Lib/http/client.py --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -786,6 +786,9 @@ line = response.fp.readline(_MAXLINE + 1) if len(line) > _MAXLINE: raise LineTooLong("header line") + if not line: + # for sites which EOF without sending a trailer + break if line == b'\r\n': break diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1521,7 +1521,8 @@ raise ImportError('no Python documentation found for %r' % thing) return object, thing else: - return thing, getattr(thing, '__name__', None) + name = getattr(thing, '__name__', None) + return thing, name if isinstance(name, str) else None def render_doc(thing, title='Python Library Documentation: %s', forceload=0, renderer=None): 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 @@ -286,6 +286,17 @@ result, doc_loc = get_pydoc_text(xml.etree) self.assertEqual(doc_loc, "", "MODULE DOCS incorrectly includes a link") + def test_non_str_name(self): + # issue14638 + # Treat illegal (non-str) name like no name + class A: + __name__ = 42 + class B: + pass + adoc = pydoc.render_doc(A()) + bdoc = pydoc.render_doc(B()) + self.assertEqual(adoc.replace("A", "B"), bdoc) + def test_not_here(self): missing_module = "test.i_am_not_here" result = str(run_pydoc(missing_module), 'ascii') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -65,6 +65,12 @@ Library ------- +- Issue #14638: pydoc now treats non-string __name__ values as if they + were missing, instead of raising an error. + +- Issue #13684: Fix httplib tunnel issue of infinite loops for certain sites + which send EOF without trailing \r\n. + - Issue #14605: Add importlib.abc.FileLoader, importlib.machinery.(FileFinder, SourceFileLoader, _SourcelessFileLoader, ExtensionFileLoader). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 20:08:49 2012 From: python-checkins at python.org (sandro.tosi) Date: Mon, 23 Apr 2012 20:08:49 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314650=3A_fix_typo_?= =?utf8?q?in_shutil=2Edisk=5Fusage=28=29_docstring=3B_patch_by_Hobson_Lane?= Message-ID: http://hg.python.org/cpython/rev/629d4c2faa87 changeset: 76505:629d4c2faa87 user: Sandro Tosi date: Mon Apr 23 20:07:15 2012 +0200 summary: Issue #14650: fix typo in shutil.disk_usage() docstring; patch by Hobson Lane files: Lib/shutil.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -822,7 +822,7 @@ def disk_usage(path): """Return disk usage statistics about the given path. - Returned valus is a named tuple with attributes 'total', 'used' and + Returned value is a named tuple with attributes 'total', 'used' and 'free', which are the amount of total, used and free space, in bytes. """ st = os.statvfs(path) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 20:47:15 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 23 Apr 2012 20:47:15 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NjQwOiBGaXgg?= =?utf8?q?typos/syntax_in_pyporting=2Erst=2E?= Message-ID: http://hg.python.org/cpython/rev/f7b002e5cac7 changeset: 76506:f7b002e5cac7 branch: 3.2 parent: 76501:9bb9604519ce user: R David Murray date: Mon Apr 23 14:44:00 2012 -0400 summary: #14640: Fix typos/syntax in pyporting.rst. Patch by Dionysios Kalofonos. files: Doc/howto/pyporting.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -39,7 +39,7 @@ Finally, you do have the option of :ref:`using 2to3 ` to translate Python 2 code into Python 3 code (with some manual help). This can take the form of branching your code and using 2to3 to start a Python 3 branch. You can -also have users perform the translation as installation time automatically so +also have users perform the translation at installation time automatically so that you only have to maintain a Python 2 codebase. Regardless of which approach you choose, porting is not as hard or @@ -234,7 +234,7 @@ ``b'py'[1:2]`` is ``'y'`` in Python 2 and ``b'y'`` in Python 3 (i.e., close enough). -You cannot concatenate bytes and strings in Python 3. But since in Python +You cannot concatenate bytes and strings in Python 3. But since Python 2 has bytes aliased to ``str``, it will succeed: ``b'a' + u'b'`` works in Python 2, but ``b'a' + 'b'`` in Python 3 is a :exc:`TypeError`. A similar issue also comes about when doing comparisons between bytes and strings. @@ -328,7 +328,7 @@ textual data, people have over the years been rather loose in their delineation of what ``str`` instances held text compared to bytes. In Python 3 you cannot be so care-free anymore and need to properly handle the difference. The key -handling this issue to make sure that **every** string literal in your +handling this issue is to make sure that **every** string literal in your Python 2 code is either syntactically of functionally marked as either bytes or text data. After this is done you then need to make sure your APIs are designed to either handle a specific type or made to be properly polymorphic. @@ -343,7 +343,7 @@ and then designating textual data with a ``u`` prefix or using the ``unicode_literals`` future statement. -If your project supports versions of Python pre-dating 2.6, then you should use +If your project supports versions of Python predating 2.6, then you should use the six_ project and its ``b()`` function to denote bytes literals. For text literals you can either use six's ``u()`` function or use a ``u`` prefix. @@ -439,7 +439,7 @@ There are two ways to solve this issue. One is to use a custom 2to3 fixer. The blog post at http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/ specifies how to do this. That will allow 2to3 to change all instances of ``def -__unicode(self): ...`` to ``def __str__(self): ...``. This does require you +__unicode(self): ...`` to ``def __str__(self): ...``. This does require that you define your ``__str__()`` method in Python 2 before your ``__unicode__()`` method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 20:47:16 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 23 Apr 2012 20:47:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_=2314640=3A_Fix_typos/syntax_in_pyporting=2Erst=2E?= Message-ID: http://hg.python.org/cpython/rev/13c30fe3f427 changeset: 76507:13c30fe3f427 parent: 76505:629d4c2faa87 parent: 76506:f7b002e5cac7 user: R David Murray date: Mon Apr 23 14:45:45 2012 -0400 summary: Merge #14640: Fix typos/syntax in pyporting.rst. Patch by Dionysios Kalofonos. files: Doc/howto/pyporting.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -39,7 +39,7 @@ Finally, you do have the option of :ref:`using 2to3 ` to translate Python 2 code into Python 3 code (with some manual help). This can take the form of branching your code and using 2to3 to start a Python 3 branch. You can -also have users perform the translation as installation time automatically so +also have users perform the translation at installation time automatically so that you only have to maintain a Python 2 codebase. Regardless of which approach you choose, porting is not as hard or @@ -234,7 +234,7 @@ ``b'py'[1:2]`` is ``'y'`` in Python 2 and ``b'y'`` in Python 3 (i.e., close enough). -You cannot concatenate bytes and strings in Python 3. But since in Python +You cannot concatenate bytes and strings in Python 3. But since Python 2 has bytes aliased to ``str``, it will succeed: ``b'a' + u'b'`` works in Python 2, but ``b'a' + 'b'`` in Python 3 is a :exc:`TypeError`. A similar issue also comes about when doing comparisons between bytes and strings. @@ -328,7 +328,7 @@ textual data, people have over the years been rather loose in their delineation of what ``str`` instances held text compared to bytes. In Python 3 you cannot be so care-free anymore and need to properly handle the difference. The key -handling this issue to make sure that **every** string literal in your +handling this issue is to make sure that **every** string literal in your Python 2 code is either syntactically of functionally marked as either bytes or text data. After this is done you then need to make sure your APIs are designed to either handle a specific type or made to be properly polymorphic. @@ -343,7 +343,7 @@ and then designating textual data with a ``u`` prefix or using the ``unicode_literals`` future statement. -If your project supports versions of Python pre-dating 2.6, then you should use +If your project supports versions of Python predating 2.6, then you should use the six_ project and its ``b()`` function to denote bytes literals. For text literals you can either use six's ``u()`` function or use a ``u`` prefix. @@ -439,7 +439,7 @@ There are two ways to solve this issue. One is to use a custom 2to3 fixer. The blog post at http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/ specifies how to do this. That will allow 2to3 to change all instances of ``def -__unicode(self): ...`` to ``def __str__(self): ...``. This does require you +__unicode(self): ...`` to ``def __str__(self): ...``. This does require that you define your ``__str__()`` method in Python 2 before your ``__unicode__()`` method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 20:47:17 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 23 Apr 2012 20:47:17 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0NjQwOiBGaXgg?= =?utf8?q?typos/syntax_in_pyporting=2Erst=2E?= Message-ID: http://hg.python.org/cpython/rev/758f5585ce52 changeset: 76508:758f5585ce52 branch: 2.7 parent: 76500:f24d8dc1a986 user: R David Murray date: Mon Apr 23 14:46:39 2012 -0400 summary: #14640: Fix typos/syntax in pyporting.rst. Patch by Dionysios Kalofonos. files: Doc/howto/pyporting.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -39,7 +39,7 @@ Finally, you do have the option of :ref:`using 2to3 ` to translate Python 2 code into Python 3 code (with some manual help). This can take the form of branching your code and using 2to3 to start a Python 3 branch. You can -also have users perform the translation as installation time automatically so +also have users perform the translation at installation time automatically so that you only have to maintain a Python 2 codebase. Regardless of which approach you choose, porting is not as hard or @@ -234,7 +234,7 @@ ``b'py'[1:2]`` is ``'y'`` in Python 2 and ``b'y'`` in Python 3 (i.e., close enough). -You cannot concatenate bytes and strings in Python 3. But since in Python +You cannot concatenate bytes and strings in Python 3. But since Python 2 has bytes aliased to ``str``, it will succeed: ``b'a' + u'b'`` works in Python 2, but ``b'a' + 'b'`` in Python 3 is a :exc:`TypeError`. A similar issue also comes about when doing comparisons between bytes and strings. @@ -328,7 +328,7 @@ textual data, people have over the years been rather loose in their delineation of what ``str`` instances held text compared to bytes. In Python 3 you cannot be so care-free anymore and need to properly handle the difference. The key -handling this issue to make sure that **every** string literal in your +handling this issue is to make sure that **every** string literal in your Python 2 code is either syntactically of functionally marked as either bytes or text data. After this is done you then need to make sure your APIs are designed to either handle a specific type or made to be properly polymorphic. @@ -343,7 +343,7 @@ and then designating textual data with a ``u`` prefix or using the ``unicode_literals`` future statement. -If your project supports versions of Python pre-dating 2.6, then you should use +If your project supports versions of Python predating 2.6, then you should use the six_ project and its ``b()`` function to denote bytes literals. For text literals you can either use six's ``u()`` function or use a ``u`` prefix. @@ -439,7 +439,7 @@ There are two ways to solve this issue. One is to use a custom 2to3 fixer. The blog post at http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/ specifies how to do this. That will allow 2to3 to change all instances of ``def -__unicode(self): ...`` to ``def __str__(self): ...``. This does require you +__unicode(self): ...`` to ``def __str__(self): ...``. This does require that you define your ``__str__()`` method in Python 2 before your ``__unicode__()`` method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 23 23:43:11 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 23 Apr 2012 23:43:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Close_=2314648=3A_Compute_c?= =?utf8?q?orrectly_maxchar_in_str=2Eformat=28=29_for_substrin?= Message-ID: http://hg.python.org/cpython/rev/139c3ae84772 changeset: 76509:139c3ae84772 parent: 76507:13c30fe3f427 user: Victor Stinner date: Mon Apr 23 23:36:38 2012 +0200 summary: Close #14648: Compute correctly maxchar in str.format() for substrin files: Include/unicodeobject.h | 9 +++++++ Lib/test/test_unicode.py | 10 ++++++- Objects/unicodeobject.c | 31 ++++++++++++++++++++++++++ Python/formatter_unicode.c | 6 +--- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -710,6 +710,15 @@ Py_ssize_t start, Py_ssize_t end); +#ifndef Py_LIMITED_API +/* Compute the maximum character of the substring unicode[start:end]. + Return 127 for an empty string. */ +PyAPI_FUNC(Py_UCS4) _PyUnicode_FindMaxChar ( + PyObject *unicode, + Py_ssize_t start, + Py_ssize_t end); +#endif + /* Copy the string into a UCS4 buffer including the null character if copy_null is set. Return NULL and raise an exception on error. Raise a ValueError if the buffer is smaller than the string. Return buffer on success. diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -924,6 +924,14 @@ self.assertRaises(ValueError, format, '', '#') self.assertRaises(ValueError, format, '', '#20') + # Non-ASCII + self.assertEqual("{0:s}{1:s}".format("ABC", "\u0410\u0411\u0412"), + 'ABC\u0410\u0411\u0412') + self.assertEqual("{0:.3s}".format("ABC\u0410\u0411\u0412"), + 'ABC') + self.assertEqual("{0:.0s}".format("ABC\u0410\u0411\u0412"), + '') + def test_format_map(self): self.assertEqual(''.format_map({}), '') self.assertEqual('a'.format_map({}), 'a') @@ -1056,8 +1064,6 @@ self.assertEqual('%f' % INF, 'inf') self.assertEqual('%F' % INF, 'INF') - self.assertEqual(format("\u0410\u0411\u0412", "s"), "???") - def test_startswith_endswith_errors(self): for meth in ('foo'.startswith, 'foo'.endswith): with self.assertRaises(TypeError) as cm: diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1957,6 +1957,37 @@ } } +Py_UCS4 +_PyUnicode_FindMaxChar(PyObject *unicode, Py_ssize_t start, Py_ssize_t end) +{ + enum PyUnicode_Kind kind; + void *startptr, *endptr; + + assert(PyUnicode_IS_READY(unicode)); + assert(0 <= start); + assert(end <= PyUnicode_GET_LENGTH(unicode)); + assert(start <= end); + + if (start == 0 && end == PyUnicode_GET_LENGTH(unicode)) + return PyUnicode_MAX_CHAR_VALUE(unicode); + + if (start == end) + return 127; + + kind = PyUnicode_KIND(unicode); + startptr = PyUnicode_DATA(unicode); + endptr = (char*)startptr + end * kind; + if (start) + startptr = (char*)startptr + start * kind; + switch(kind) + { + case PyUnicode_1BYTE_KIND: return ucs1lib_find_max_char(startptr, endptr); + case PyUnicode_2BYTE_KIND: return ucs2lib_find_max_char(startptr, endptr); + default: + case PyUnicode_4BYTE_KIND: return ucs4lib_find_max_char(startptr, endptr); + } +} + /* Ensure that a string uses the most efficient storage, if it is not the case: create a new string with of the right kind. Write NULL into *p_unicode on error. */ diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -716,7 +716,7 @@ Py_ssize_t pos; Py_ssize_t len = PyUnicode_GET_LENGTH(value); PyObject *result = NULL; - Py_UCS4 maxchar = 127; + Py_UCS4 maxchar; /* sign is not allowed on strings */ if (format->sign != '\0') { @@ -747,11 +747,9 @@ len = format->precision; } - if (len) - maxchar = PyUnicode_MAX_CHAR_VALUE(value); - calc_padding(len, format->width, format->align, &lpad, &rpad, &total); + maxchar = _PyUnicode_FindMaxChar(value, 0, len); if (lpad != 0 || rpad != 0) maxchar = Py_MAX(maxchar, format->fill_char); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 00:00:43 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Apr 2012 00:00:43 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_simplify_and_reformat?= Message-ID: http://hg.python.org/cpython/rev/a9ddade7eb97 changeset: 76510:a9ddade7eb97 user: Benjamin Peterson date: Mon Apr 23 18:00:25 2012 -0400 summary: simplify and reformat files: Objects/unicodeobject.c | 20 +++++++++++--------- 1 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1975,16 +1975,18 @@ return 127; kind = PyUnicode_KIND(unicode); - startptr = PyUnicode_DATA(unicode); - endptr = (char*)startptr + end * kind; - if (start) - startptr = (char*)startptr + start * kind; - switch(kind) - { - case PyUnicode_1BYTE_KIND: return ucs1lib_find_max_char(startptr, endptr); - case PyUnicode_2BYTE_KIND: return ucs2lib_find_max_char(startptr, endptr); + startptr = PyUnicode_DATA(unicode) + start * kind; + endptr = startptr + end * kind; + switch(kind) { + case PyUnicode_1BYTE_KIND: + return ucs1lib_find_max_char(startptr, endptr); + case PyUnicode_2BYTE_KIND: + return ucs2lib_find_max_char(startptr, endptr); + case PyUnicode_4BYTE_KIND: + return ucs4lib_find_max_char(startptr, endptr); default: - case PyUnicode_4BYTE_KIND: return ucs4lib_find_max_char(startptr, endptr); + assert(0); + return 0; } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 00:07:11 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Apr 2012 00:07:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_use_correct_base_ptr?= Message-ID: http://hg.python.org/cpython/rev/8dbcedfd13f8 changeset: 76511:8dbcedfd13f8 user: Benjamin Peterson date: Mon Apr 23 18:07:01 2012 -0400 summary: use correct base ptr files: Objects/unicodeobject.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1975,8 +1975,9 @@ return 127; kind = PyUnicode_KIND(unicode); - startptr = PyUnicode_DATA(unicode) + start * kind; + startptr = PyUnicode_DATA(unicode); endptr = startptr + end * kind; + startptr += start * kind; switch(kind) { case PyUnicode_1BYTE_KIND: return ucs1lib_find_max_char(startptr, endptr); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 00:30:28 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 24 Apr 2012 00:30:28 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Rename_clock=5Fprec?= =?utf8?q?ision=2Epy_to_clock=5Fresolution=2Epy?= Message-ID: http://hg.python.org/peps/rev/1d4625d37102 changeset: 4296:1d4625d37102 user: Victor Stinner date: Tue Apr 24 00:12:53 2012 +0200 summary: PEP 418: Rename clock_precision.py to clock_resolution.py files: pep-0418/clock_precision.py | 0 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/pep-0418/clock_precision.py b/pep-0418/clock_resolution.py rename from pep-0418/clock_precision.py rename to pep-0418/clock_resolution.py -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 00:30:29 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 24 Apr 2012 00:30:29 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Replace_=22Precisio?= =?utf8?q?n_in_Python=22_with_=22Python_Resolution=22?= Message-ID: http://hg.python.org/peps/rev/f8dd1187c2c6 changeset: 4297:f8dd1187c2c6 user: Victor Stinner date: Tue Apr 24 00:14:51 2012 +0200 summary: PEP 418: Replace "Precision in Python" with "Python Resolution" files: pep-0418.txt | 98 ++++++++++++++++++++-------------------- 1 files changed, 49 insertions(+), 49 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -930,26 +930,26 @@ Examples of clock precision on x86_64: -========================= ================ ========= =================== -Name Operating system Precision Precision in Python -========================= ================ ========= =================== -QueryPerformanceCounter Windows Seven 10 ns 10 ns -CLOCK_HIGHRES SunOS 5.11 2 ns 265 ns -CLOCK_MONOTONIC Linux 3.0 1 ns 322 ns -CLOCK_MONOTONIC_RAW Linux 3.3 1 ns 628 ns -CLOCK_BOOTTIME Linux 3.3 1 ns 628 ns -mach_absolute_time() Mac OS 10.6 1 ns 3 ?s -CLOCK_MONOTONIC FreeBSD 8.2 11 ns 5 ?s -CLOCK_MONOTONIC OpenBSD 5.0 10 ms 5 ?s -CLOCK_UPTIME FreeBSD 8.2 11 ns 6 ?s -CLOCK_MONOTONIC_COARSE Linux 3.3 1 ms 1 ms -CLOCK_MONOTONIC_COARSE Linux 3.0 4 ms 4 ms -GetTickCount64() Windows Seven 16 ms 15 ms -========================= ================ ========= =================== +========================= ================ ========= ================= +Name Operating system Precision Python Resolution +========================= ================ ========= ================= +QueryPerformanceCounter Windows Seven 10 ns 10 ns +CLOCK_HIGHRES SunOS 5.11 2 ns 265 ns +CLOCK_MONOTONIC Linux 3.0 1 ns 322 ns +CLOCK_MONOTONIC_RAW Linux 3.3 1 ns 628 ns +CLOCK_BOOTTIME Linux 3.3 1 ns 628 ns +mach_absolute_time() Mac OS 10.6 1 ns 3 ?s +CLOCK_MONOTONIC FreeBSD 8.2 11 ns 5 ?s +CLOCK_MONOTONIC OpenBSD 5.0 10 ms 5 ?s +CLOCK_UPTIME FreeBSD 8.2 11 ns 6 ?s +CLOCK_MONOTONIC_COARSE Linux 3.3 1 ms 1 ms +CLOCK_MONOTONIC_COARSE Linux 3.0 4 ms 4 ms +GetTickCount64() Windows Seven 16 ms 15 ms +========================= ================ ========= ================= -The "Precision in Python" column was filled using the -`clock_precision.py -`_ +The "Python Resolution" column was filled using the +`clock_resolution.py +`_ program. mach_absolute_time @@ -1185,23 +1185,23 @@ Examples of clock precision on x86_64: -========================= ================ ========= =================== -Name Operating system Precision Precision in Python -========================= ================ ========= =================== -CLOCK_REALTIME SunOS 5.11 10 ms 238 ns -CLOCK_REALTIME Linux 3.0 1 ns 238 ns -gettimeofday() Mac OS 10.6 1 ?s 4 ?s -CLOCK_REALTIME FreeBSD 8.2 11 ns 6 ?s -CLOCK_REALTIME OpenBSD 5.0 10 ms 5 ?s -CLOCK_REALTIME_COARSE Linux 3.3 1 ms 1 ms -CLOCK_REALTIME_COARSE Linux 3.0 4 ms 4 ms -GetSystemTimeAsFileTime() Windows Seven 16 ms 1 ms -ftime() Windows Seven \- 1 ms -========================= ================ ========= =================== +========================= ================ ========= ================= +Name Operating system Precision Python Resolution +========================= ================ ========= ================= +CLOCK_REALTIME SunOS 5.11 10 ms 238 ns +CLOCK_REALTIME Linux 3.0 1 ns 238 ns +gettimeofday() Mac OS 10.6 1 ?s 4 ?s +CLOCK_REALTIME FreeBSD 8.2 11 ns 6 ?s +CLOCK_REALTIME OpenBSD 5.0 10 ms 5 ?s +CLOCK_REALTIME_COARSE Linux 3.3 1 ms 1 ms +CLOCK_REALTIME_COARSE Linux 3.0 4 ms 4 ms +GetSystemTimeAsFileTime() Windows Seven 16 ms 1 ms +ftime() Windows Seven \- 1 ms +========================= ================ ========= ================= -The "Precision in Python" column was filled using the -`clock_precision.py -`_ +The "Python Resolution" column was filled using the +`clock_resolution.py +`_ program. @@ -1255,7 +1255,7 @@ Examples of clock precision on x86_64: ========================= ================ ========= =================== -Name Operating system Precision Precision in Python +Name Operating system Precision Python Resolution ========================= ================ ========= =================== CLOCK_PROCESS_CPUTIME_ID Linux 3.3 1 ns 1 ns CLOCK_PROF FreeBSD 8.2 10 ms 1 ?s @@ -1279,9 +1279,9 @@ clock() Windows Seven 1 ms 1 ms ========================= ================ ========= =================== -The "Precision in Python" column was filled using the -`clock_precision.py -`_ +The "Python Resolution" column was filled using the +`clock_resolution.py +`_ program. Functions @@ -1330,17 +1330,17 @@ Examples of clock precision on x86_64: -========================= ================ =============== =================== -Name Operating system Precision Precision in Python -========================= ================ =============== =================== -CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s 1 ?s -CLOCK_THREAD_CPUTIME_ID Linux 3.3 1 ns 649 ns -GetThreadTimes() Windows Seven 16 ms 16 ms -========================= ================ =============== =================== +========================= ================ =============== ================= +Name Operating system Precision Python Resolution +========================= ================ =============== ================= +CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s 1 ?s +CLOCK_THREAD_CPUTIME_ID Linux 3.3 1 ns 649 ns +GetThreadTimes() Windows Seven 16 ms 16 ms +========================= ================ =============== ================= -The "Precision in Python" column was filled using the -`clock_precision.py -`_ +The "Python Resolution" column was filled using the +`clock_resolution.py +`_ program. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 00:30:30 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 24 Apr 2012 00:30:30 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Replace_=22Resoluti?= =?utf8?q?on=22_column_with_=22C_Resolution=22=2C_and_=22Precision=22_with?= Message-ID: http://hg.python.org/peps/rev/33b504ccfee6 changeset: 4298:33b504ccfee6 user: Victor Stinner date: Tue Apr 24 00:24:08 2012 +0200 summary: PEP 418: Replace "Resolution" column with "C Resolution", and "Precision" with "OS Resolution" Document also these two columns. files: pep-0418.txt | 279 +++++++++++++++++++++----------------- 1 files changed, 151 insertions(+), 128 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -912,43 +912,48 @@ Monotonic Clocks ---------------- -========================= ========== =============== ============= =============== -Name Resolution Adjusted Include sleep Include suspend -========================= ========== =============== ============= =============== -gethrtime() 1 ns No Yes Yes -CLOCK_HIGHRES 1 ns No Yes Yes -CLOCK_MONOTONIC 1 ns Slewed on Linux Yes No -CLOCK_MONOTONIC_COARSE 1 ns Slewed on Linux Yes No -CLOCK_MONOTONIC_RAW 1 ns No Yes No -CLOCK_BOOTTIME 1 ns ? Yes Yes -CLOCK_UPTIME 1 ns No Yes ? -mach_absolute_time() 1 ns No Yes No -QueryPerformanceCounter() \- No Yes ? -GetTickCount[64]() 1 ms No Yes Yes -timeGetTime() 1 ms No Yes ? -========================= ========== =============== ============= =============== +========================= ============ =============== ============= =============== +Name C Resolution Adjusted Include Sleep Include Suspend +========================= ============ =============== ============= =============== +gethrtime() 1 ns No Yes Yes +CLOCK_HIGHRES 1 ns No Yes Yes +CLOCK_MONOTONIC 1 ns Slewed on Linux Yes No +CLOCK_MONOTONIC_COARSE 1 ns Slewed on Linux Yes No +CLOCK_MONOTONIC_RAW 1 ns No Yes No +CLOCK_BOOTTIME 1 ns ? Yes Yes +CLOCK_UPTIME 1 ns No Yes ? +mach_absolute_time() 1 ns No Yes No +QueryPerformanceCounter() \- No Yes ? +GetTickCount[64]() 1 ms No Yes Yes +timeGetTime() 1 ms No Yes ? +========================= ============ =============== ============= =============== + +The "C Resolution" column is the resolution of the underlying C +structure. Examples of clock precision on x86_64: -========================= ================ ========= ================= -Name Operating system Precision Python Resolution -========================= ================ ========= ================= -QueryPerformanceCounter Windows Seven 10 ns 10 ns -CLOCK_HIGHRES SunOS 5.11 2 ns 265 ns -CLOCK_MONOTONIC Linux 3.0 1 ns 322 ns -CLOCK_MONOTONIC_RAW Linux 3.3 1 ns 628 ns -CLOCK_BOOTTIME Linux 3.3 1 ns 628 ns -mach_absolute_time() Mac OS 10.6 1 ns 3 ?s -CLOCK_MONOTONIC FreeBSD 8.2 11 ns 5 ?s -CLOCK_MONOTONIC OpenBSD 5.0 10 ms 5 ?s -CLOCK_UPTIME FreeBSD 8.2 11 ns 6 ?s -CLOCK_MONOTONIC_COARSE Linux 3.3 1 ms 1 ms -CLOCK_MONOTONIC_COARSE Linux 3.0 4 ms 4 ms -GetTickCount64() Windows Seven 16 ms 15 ms -========================= ================ ========= ================= +========================= ================ ============= ================= +Name Operating system OS Resolution Python Resolution +========================= ================ ============= ================= +QueryPerformanceCounter Windows Seven 10 ns 10 ns +CLOCK_HIGHRES SunOS 5.11 2 ns 265 ns +CLOCK_MONOTONIC Linux 3.0 1 ns 322 ns +CLOCK_MONOTONIC_RAW Linux 3.3 1 ns 628 ns +CLOCK_BOOTTIME Linux 3.3 1 ns 628 ns +mach_absolute_time() Mac OS 10.6 1 ns 3 ?s +CLOCK_MONOTONIC FreeBSD 8.2 11 ns 5 ?s +CLOCK_MONOTONIC OpenBSD 5.0 10 ms 5 ?s +CLOCK_UPTIME FreeBSD 8.2 11 ns 6 ?s +CLOCK_MONOTONIC_COARSE Linux 3.3 1 ms 1 ms +CLOCK_MONOTONIC_COARSE Linux 3.0 4 ms 4 ms +GetTickCount64() Windows Seven 16 ms 15 ms +========================= ================ ============= ================= -The "Python Resolution" column was filled using the -`clock_resolution.py +The "OS Resolution" is the resolution announced by the operating +system. +The "Python Resolution" is the smallest difference between two calls +to the time function computed in Python using the `clock_resolution.py `_ program. @@ -1172,35 +1177,40 @@ System Time ----------- -========================= =============== ============= =============== -Name Resolution Include sleep Include suspend -========================= =============== ============= =============== -CLOCK_REALTIME 1 ns Yes Yes -CLOCK_REALTIME_COARSE 1 ns Yes Yes -GetSystemTimeAsFileTime 100 ns Yes Yes -gettimeofday() 1 ?s Yes Yes -ftime() 1 ms Yes Yes -time() 1 sec Yes Yes -========================= =============== ============= =============== +========================= ============ ============= =============== +Name C Resolution Include Sleep Include Suspend +========================= ============ ============= =============== +CLOCK_REALTIME 1 ns Yes Yes +CLOCK_REALTIME_COARSE 1 ns Yes Yes +GetSystemTimeAsFileTime 100 ns Yes Yes +gettimeofday() 1 ?s Yes Yes +ftime() 1 ms Yes Yes +time() 1 sec Yes Yes +========================= ============ ============= =============== + +The "C Resolution" column is the resolution of the underlying C +structure. Examples of clock precision on x86_64: -========================= ================ ========= ================= -Name Operating system Precision Python Resolution -========================= ================ ========= ================= -CLOCK_REALTIME SunOS 5.11 10 ms 238 ns -CLOCK_REALTIME Linux 3.0 1 ns 238 ns -gettimeofday() Mac OS 10.6 1 ?s 4 ?s -CLOCK_REALTIME FreeBSD 8.2 11 ns 6 ?s -CLOCK_REALTIME OpenBSD 5.0 10 ms 5 ?s -CLOCK_REALTIME_COARSE Linux 3.3 1 ms 1 ms -CLOCK_REALTIME_COARSE Linux 3.0 4 ms 4 ms -GetSystemTimeAsFileTime() Windows Seven 16 ms 1 ms -ftime() Windows Seven \- 1 ms -========================= ================ ========= ================= +========================= ================ ============= ================= +Name Operating system OS Resolution Python Resolution +========================= ================ ============= ================= +CLOCK_REALTIME SunOS 5.11 10 ms 238 ns +CLOCK_REALTIME Linux 3.0 1 ns 238 ns +gettimeofday() Mac OS 10.6 1 ?s 4 ?s +CLOCK_REALTIME FreeBSD 8.2 11 ns 6 ?s +CLOCK_REALTIME OpenBSD 5.0 10 ms 5 ?s +CLOCK_REALTIME_COARSE Linux 3.3 1 ms 1 ms +CLOCK_REALTIME_COARSE Linux 3.0 4 ms 4 ms +GetSystemTimeAsFileTime() Windows Seven 16 ms 1 ms +ftime() Windows Seven \- 1 ms +========================= ================ ============= ================= -The "Python Resolution" column was filled using the -`clock_resolution.py +The "OS Resolution" is the resolution announced by the operating +system. +The "Python Resolution" is the smallest difference between two calls +to the time function computed in Python using the `clock_resolution.py `_ program. @@ -1242,45 +1252,50 @@ The process time cannot be set. It is not monotonic: the clocks stop while the process is idle. -========================= ========== ============================ =============== -Name Resolution Include sleep Include suspend -========================= ========== ============================ =============== -GetProcessTimes() 100 ns No No -CLOCK_PROCESS_CPUTIME_ID 1 ns No No -getrusage(RUSAGE_SELF) 1 ?s No No -times() \- No No -clock() \- Yes on Windows, No otherwise No -========================= ========== ============================ =============== +========================= ============ ============================ =============== +Name C Resolution Include Sleep Include Suspend +========================= ============ ============================ =============== +GetProcessTimes() 100 ns No No +CLOCK_PROCESS_CPUTIME_ID 1 ns No No +getrusage(RUSAGE_SELF) 1 ?s No No +times() \- No No +clock() \- Yes on Windows, No otherwise No +========================= ============ ============================ =============== + +The "C Resolution" column is the resolution of the underlying C +structure. Examples of clock precision on x86_64: -========================= ================ ========= =================== -Name Operating system Precision Python Resolution -========================= ================ ========= =================== -CLOCK_PROCESS_CPUTIME_ID Linux 3.3 1 ns 1 ns -CLOCK_PROF FreeBSD 8.2 10 ms 1 ?s -getrusage(RUSAGE_SELF) FreeBSD 8.2 \- 1 ?s -getrusage(RUSAGE_SELF) SunOS 5.11 \- 1 ?s -CLOCK_PROCESS_CPUTIME_ID Linux 3.0 1 ns 1 ?s -getrusage(RUSAGE_SELF) Mac OS 10.6 \- 5 ?s -clock() Mac OS 10.6 1 ?s 5 ?s -CLOCK_PROF OpenBSD 5.0 \- 5 ?s -getrusage(RUSAGE_SELF) Linux 3.0 \- 4 ms -getrusage(RUSAGE_SELF) OpenBSD 5.0 \- 8 ms -clock() FreeBSD 8.2 8 ms 8 ms -clock() Linux 3.0 1 ?s 10 ms -times() Linux 3.0 10 ms 10 ms -clock() OpenBSD 5.0 10 ms 10 ms -times() OpenBSD 5.0 10 ms 10 ms -times() Mac OS 10.6 10 ms 10 ms -clock() SunOS 5.11 1 ?s 10 ms -times() SunOS 5.11 1 ?s 10 ms -GetProcessTimes() Windows Seven 16 ms 16 ms -clock() Windows Seven 1 ms 1 ms -========================= ================ ========= =================== +========================= ================ ============= =================== +Name Operating system OS Resolution Python Resolution +========================= ================ ============= =================== +CLOCK_PROCESS_CPUTIME_ID Linux 3.3 1 ns 1 ns +CLOCK_PROF FreeBSD 8.2 10 ms 1 ?s +getrusage(RUSAGE_SELF) FreeBSD 8.2 \- 1 ?s +getrusage(RUSAGE_SELF) SunOS 5.11 \- 1 ?s +CLOCK_PROCESS_CPUTIME_ID Linux 3.0 1 ns 1 ?s +getrusage(RUSAGE_SELF) Mac OS 10.6 \- 5 ?s +clock() Mac OS 10.6 1 ?s 5 ?s +CLOCK_PROF OpenBSD 5.0 \- 5 ?s +getrusage(RUSAGE_SELF) Linux 3.0 \- 4 ms +getrusage(RUSAGE_SELF) OpenBSD 5.0 \- 8 ms +clock() FreeBSD 8.2 8 ms 8 ms +clock() Linux 3.0 1 ?s 10 ms +times() Linux 3.0 10 ms 10 ms +clock() OpenBSD 5.0 10 ms 10 ms +times() OpenBSD 5.0 10 ms 10 ms +times() Mac OS 10.6 10 ms 10 ms +clock() SunOS 5.11 1 ?s 10 ms +times() SunOS 5.11 1 ?s 10 ms +GetProcessTimes() Windows Seven 16 ms 16 ms +clock() Windows Seven 1 ms 1 ms +========================= ================ ============= =================== -The "Python Resolution" column was filled using the -`clock_resolution.py +The "OS Resolution" is the resolution announced by the operating +system. +The "Python Resolution" is the smallest difference between two calls +to the time function computed in Python using the `clock_resolution.py `_ program. @@ -1321,25 +1336,30 @@ The thread time cannot be set. It is not monotonic: the clocks stop while the thread is idle. -========================= ========== ============= =============== -Name Resolution Include sleep Include suspend -========================= ========== ============= =============== -CLOCK_THREAD_CPUTIME_ID 1 ns Yes Epoch changes -GetThreadTimes() 100 ns No ? -========================= ========== ============= =============== +========================= ============ ============= =============== +Name C Resolution Include Sleep Include Suspend +========================= ============ ============= =============== +CLOCK_THREAD_CPUTIME_ID 1 ns Yes Epoch changes +GetThreadTimes() 100 ns No ? +========================= ============ ============= =============== + +The "C Resolution" column is the resolution of the underlying C +structure. Examples of clock precision on x86_64: -========================= ================ =============== ================= -Name Operating system Precision Python Resolution -========================= ================ =============== ================= -CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s 1 ?s -CLOCK_THREAD_CPUTIME_ID Linux 3.3 1 ns 649 ns -GetThreadTimes() Windows Seven 16 ms 16 ms -========================= ================ =============== ================= +========================= ================ ============= ================= +Name Operating system OS Resolution Python Resolution +========================= ================ ============= ================= +CLOCK_THREAD_CPUTIME_ID FreeBSD 8.2 1 ?s 1 ?s +CLOCK_THREAD_CPUTIME_ID Linux 3.3 1 ns 649 ns +GetThreadTimes() Windows Seven 16 ms 16 ms +========================= ================ ============= ================= -The "Python Resolution" column was filled using the -`clock_resolution.py +The "OS Resolution" is the resolution announced by the operating +system. +The "Python Resolution" is the smallest difference between two calls +to the time function computed in Python using the `clock_resolution.py `_ program. @@ -1388,29 +1408,32 @@ Sleep can be interrupted by a signal: the function fails with EINTR. -======================== ========== -Name Resolution -======================== ========== -nanosleep() 1 ns -clock_nanosleep() 1 ns -usleep() 1 ?s -delay() 1 ?s -sleep() 1 sec -======================== ========== +======================== ============ +Name C Resolution +======================== ============ +nanosleep() 1 ns +clock_nanosleep() 1 ns +usleep() 1 ?s +delay() 1 ?s +sleep() 1 sec +======================== ============ Other functions: -======================== ========== -Name Resolution -======================== ========== -sigtimedwait() 1 ns -pthread_cond_timedwait() 1 ns -sem_timedwait() 1 ns -select() 1 ?s -epoll() 1 ms -poll() 1 ms -WaitForSingleObject() 1 ms -======================== ========== +======================== ============ +Name C Resolution +======================== ============ +sigtimedwait() 1 ns +pthread_cond_timedwait() 1 ns +sem_timedwait() 1 ns +select() 1 ?s +epoll() 1 ms +poll() 1 ms +WaitForSingleObject() 1 ms +======================== ============ + +The "C Resolution" column is the resolution of the underlying C +structure. Functions -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 00:30:30 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 24 Apr 2012 00:30:30 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Replace_misuse_of_p?= =?utf8?q?recision_with_resolution?= Message-ID: http://hg.python.org/peps/rev/72793ac1a4a8 changeset: 4299:72793ac1a4a8 user: Victor Stinner date: Tue Apr 24 00:30:23 2012 +0200 summary: PEP 418: Replace misuse of precision with resolution files: pep-0418.txt | 56 +++++++++++++++++++-------------------- 1 files changed, 27 insertions(+), 29 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -31,7 +31,7 @@ To measure the performance of a function, ``time.clock()`` can be used but it is very different on Windows and on Unix. On Windows, ``time.clock()`` includes time elapsed during sleep, whereas it does -not on Unix. ``time.clock()`` precision is very good on Windows, but +not on Unix. ``time.clock()`` resolution is very good on Windows, but very bad on Unix. The new ``time.perf_counter()`` function should be used instead to always get the most precise performance counter with a portable behaviour (ex: include time spend during sleep). @@ -39,18 +39,18 @@ Until now, Python did not provide directly a portable function to measure CPU time. ``time.clock()`` can be used on Unix, but it has bad -precision. ``resource.getrusage()`` or ``os.times()`` can also be +resolution. ``resource.getrusage()`` or ``os.times()`` can also be used on Unix, but they require to compute the sum of time spent in kernel space and user space. The new ``time.process_time()`` function acts as a portable counter that always measures CPU time (excluding time elapsed during sleep) and has the best available -precision. +resolution. Each operating system implements clocks and performance counters differently, and it is useful to know exactly which function is used -and some properties of the clock like its resolution and its -precision. The new ``time.get_clock_info()`` function gives access to -all available information about each Python time function. +and some properties of the clock like its resolution. The new +``time.get_clock_info()`` function gives access to all available +information about each Python time function. New functions: @@ -67,7 +67,7 @@ * time.perf_counter(): trace and timeit modules, pybench program * time.process_time(): profile module * time.get_clock_info(): pybench program to display information about the - timer like the precision or the resolution + timer like the resolution The ``time.clock()`` function is deprecated because it is not portable: it behaves differently depending on the operating system. @@ -126,8 +126,6 @@ * Optional keys: - * ``"precision"`` (float): precision in seconds of the clock - reported by the operating system. * ``"is_adjusted"`` (bool): True if the clock is adjusted (e.g. by a NTP daemon). @@ -189,14 +187,14 @@ On Windows, ``QueryPerformanceCounter()`` is not used even though it -has a better precision than ``GetTickCount()``. It is not reliable +has a better resolution than ``GetTickCount()``. It is not reliable and has too many issues. time.perf_counter() ^^^^^^^^^^^^^^^^^^^ -Performance counter with the highest available precision to measure a +Performance counter with the highest available resolution to measure a short duration. It does include time elapsed during sleep and is system-wide. The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls @@ -385,7 +383,7 @@ ^^^^^^^^^^^^ On Unix, return the current processor time as a floating point number -expressed in seconds. It is process-wide by definition. The precision, +expressed in seconds. It is process-wide by definition. The resolution, and in fact the very definition of the meaning of "processor time", depends on that of the C function of the same name, but in any case, this is the function to use for benchmarking Python or timing @@ -523,7 +521,7 @@ * time.MONOTONIC: clock cannot go backward * time.STEADY: clock rate is steady * time.ADJUSTED: clock may be adjusted, for example by NTP -* time.HIGHRES: clock with the highest precision +* time.HIGHRES: clock with the highest resolution It returns a clock object with a .now() method returning the current time. The clock object is annotated with metadata describing the clock feature set; @@ -931,7 +929,7 @@ The "C Resolution" column is the resolution of the underlying C structure. -Examples of clock precision on x86_64: +Examples of clock resolution on x86_64: ========================= ================ ============= ================= Name Operating system OS Resolution Python Resolution @@ -978,7 +976,7 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW represent monotonic time since -some unspecified starting point. They cannot be set. The precision +some unspecified starting point. They cannot be set. The resolution can be read using ``clock_getres()``. Documentation: refer to the manual page of your operating system. @@ -1031,7 +1029,7 @@ High-resolution performance counter. It is monotonic. The frequency of the counter can be read using QueryPerformanceFrequency(). -The precision is 1 / QueryPerformanceFrequency(). +The resolution is 1 / QueryPerformanceFrequency(). It has a much higher resolution, but has lower long term precision than GetTickCount() and timeGetTime() clocks. For example, it will @@ -1097,7 +1095,7 @@ `_, `GetTickCount64() `_. -The precision can be read using GetSystemTimeAdjustment(). +The resolution can be read using GetSystemTimeAdjustment(). The elapsed time retrieved by GetTickCount() or GetTickCount64() includes time the system spends in sleep or hibernation. @@ -1153,7 +1151,7 @@ created with a clockid_t value of CLOCK_HIGHRES, the system will attempt to use an optimal hardware source. -The precision of CLOCK_HIGHRES can be read using ``clock_getres()``. +The resolution of CLOCK_HIGHRES can be read using ``clock_getres()``. Solaris: gethrtime ^^^^^^^^^^^^^^^^^^ @@ -1191,7 +1189,7 @@ The "C Resolution" column is the resolution of the underlying C structure. -Examples of clock precision on x86_64: +Examples of clock resolution on x86_64: ========================= ================ ============= ================= Name Operating system OS Resolution Python Resolution @@ -1219,7 +1217,7 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The system time can be read using GetSystemTimeAsFileTime(), ftime() and -time(). The precision of the system time can be read using +time(). The resolution of the system time can be read using GetSystemTimeAdjustment(). Read the `GetSystemTimeAsFileTime() documentation @@ -1231,7 +1229,7 @@ ^^^^^^^^^^^^^^^^^^^ gettimeofday(), ftime(), time() and clock_gettime(CLOCK_REALTIME) return -the system time. The precision of CLOCK_REALTIME can be read using +the system time. The resolution of CLOCK_REALTIME can be read using clock_getres(). The system time can be set using settimeofday() or @@ -1265,7 +1263,7 @@ The "C Resolution" column is the resolution of the underlying C structure. -Examples of clock precision on x86_64: +Examples of clock resolution on x86_64: ========================= ================ ============= =================== Name Operating system OS Resolution Python Resolution @@ -1304,10 +1302,10 @@ * Windows: `GetProcessTimes() `_. - The precision can be read using GetSystemTimeAdjustment(). + The resolution can be read using GetSystemTimeAdjustment(). * clock_gettime(CLOCK_PROCESS_CPUTIME_ID): High-resolution per-process - timer from the CPU. The precision can be read using clock_getres(). -* clock(). The precision is 1 / CLOCKS_PER_SEC. + timer from the CPU. The resolution can be read using clock_getres(). +* clock(). The resolution is 1 / CLOCKS_PER_SEC. * Windows: The elapsed wall-clock time since the start of the process (elapsed time in seconds times CLOCKS_PER_SEC). Include @@ -1317,7 +1315,7 @@ * getrusage(RUSAGE_SELF) returns a structure of resource usage of the currenet process. ru_utime is user CPU time and ru_stime is the system CPU time. -* times(): structure of process times. The precision is 1 / ticks_per_seconds, +* times(): structure of process times. The resolution is 1 / ticks_per_seconds, where ticks_per_seconds is sysconf(_SC_CLK_TCK) or the HZ constant. Python source code includes a portable library to get the process time (CPU @@ -1346,7 +1344,7 @@ The "C Resolution" column is the resolution of the underlying C structure. -Examples of clock precision on x86_64: +Examples of clock resolution on x86_64: ========================= ================ ============= ================= Name Operating system OS Resolution Python Resolution @@ -1369,10 +1367,10 @@ * Windows: `GetThreadTimes() `_. - The precision can be read using GetSystemTimeAdjustment(). + The resolution can be read using GetSystemTimeAdjustment(). * clock_gettime(CLOCK_THREAD_CPUTIME_ID): Thread-specific CPU-time clock. It uses a number of CPU cycles, not a number of seconds. - The precision can be read using of clock_getres(). + The resolution can be read using of clock_getres(). See also the `QueryThreadCycleTime() function `_ -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 00:59:50 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 24 Apr 2012 00:59:50 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_typoe?= Message-ID: http://hg.python.org/peps/rev/6f1e2b79b0f3 changeset: 4300:6f1e2b79b0f3 user: Victor Stinner date: Tue Apr 24 00:59:45 2012 +0200 summary: PEP 418: typoe files: pep-0418.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -91,7 +91,7 @@ * No time.thread_time() function is proposed by this PEP because it is not needed by Python standard library nor a common asked feature. Such function would only be available on Windows and Linux. On - Linux, it is possible use use + Linux, it is possible to use ``time.clock_gettime(CLOCK_THREAD_CPUTIME_ID)``. On Windows, ctypes or another module can be used to call the ``GetThreadTimes()`` function. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 03:45:45 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Apr 2012 03:45:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_make_pointer_arith_c89?= Message-ID: http://hg.python.org/cpython/rev/de0b6e0d8cb9 changeset: 76512:de0b6e0d8cb9 user: Benjamin Peterson date: Mon Apr 23 21:45:40 2012 -0400 summary: make pointer arith c89 files: Objects/unicodeobject.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1976,8 +1976,8 @@ kind = PyUnicode_KIND(unicode); startptr = PyUnicode_DATA(unicode); - endptr = startptr + end * kind; - startptr += start * kind; + endptr = (char *)startptr + end * kind; + startptr = (char *)startptr + start * kind; switch(kind) { case PyUnicode_1BYTE_KIND: return ucs1lib_find_max_char(startptr, endptr); -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Apr 24 05:36:41 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 24 Apr 2012 05:36:41 +0200 Subject: [Python-checkins] Daily reference leaks (8dbcedfd13f8): sum=15528 Message-ID: results for 8dbcedfd13f8 on branch "default" -------------------------------------------- test_itertools leaked [44, 44, 44] references, sum=132 test_robotparser leaked [103, 103, 103] references, sum=309 test_ssl leaked [103, 103, 103] references, sum=309 test_tempfile leaked [2, 2, 2] references, sum=6 test_urllib leaked [103, 103, 103] references, sum=309 test_urllib2 leaked [3208, 3208, 3208] references, sum=9624 test_urllib2_localnet leaked [1078, 1078, 1078] references, sum=3234 test_urllib2net leaked [432, 432, 432] references, sum=1296 test_urllibnet leaked [103, 103, 103] references, sum=309 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogyhNnGk', '-x'] From python-checkins at python.org Tue Apr 24 06:27:07 2012 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 24 Apr 2012 06:27:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Reorder_the_ent?= =?utf8?q?ries_to_put_the_type_specific_technique_last=2E?= Message-ID: http://hg.python.org/cpython/rev/e2a3260f1718 changeset: 76513:e2a3260f1718 branch: 2.7 parent: 76480:db26c4daecbb user: Raymond Hettinger date: Mon Apr 23 21:24:15 2012 -0700 summary: Reorder the entries to put the type specific technique last. files: Doc/tutorial/datastructures.rst | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -577,16 +577,6 @@ Looping Techniques ================== -When looping through dictionaries, the key and corresponding value can be -retrieved at the same time using the :meth:`iteritems` method. :: - - >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} - >>> for k, v in knights.iteritems(): - ... print k, v - ... - gallahad the pure - robin the brave - When looping through a sequence, the position index and corresponding value can be retrieved at the same time using the :func:`enumerate` function. :: @@ -633,6 +623,16 @@ orange pear +When looping through dictionaries, the key and corresponding value can be +retrieved at the same time using the :meth:`iteritems` method. :: + + >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} + >>> for k, v in knights.iteritems(): + ... print k, v + ... + gallahad the pure + robin the brave + .. _tut-conditions: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 06:27:07 2012 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 24 Apr 2012 06:27:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Improve_section?= =?utf8?q?_heading_for_better_discoverability=2E?= Message-ID: http://hg.python.org/cpython/rev/15cb8d80ecc8 changeset: 76514:15cb8d80ecc8 branch: 2.7 user: Raymond Hettinger date: Mon Apr 23 21:26:35 2012 -0700 summary: Improve section heading for better discoverability. files: Doc/tutorial/classes.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -534,8 +534,8 @@ .. _tut-private: -Private Variables -================= +Private Variables and Class-local References +============================================ "Private" instance variables that cannot be accessed except from inside an object don't exist in Python. However, there is a convention that is followed -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 06:27:11 2012 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 24 Apr 2012 06:27:11 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf8?q?_merge?= Message-ID: http://hg.python.org/cpython/rev/6a60359556f9 changeset: 76515:6a60359556f9 branch: 2.7 parent: 76514:15cb8d80ecc8 parent: 76508:758f5585ce52 user: Raymond Hettinger date: Mon Apr 23 21:26:58 2012 -0700 summary: merge files: Doc/howto/pyporting.rst | 10 +++++----- Doc/howto/sockets.rst | 4 ++-- Lib/httplib.py | 6 +++++- Lib/pydoc.py | 3 ++- Lib/test/test_pydoc.py | 11 +++++++++++ Lib/test/test_thread.py | 2 +- Misc/ACKS | 1 + Misc/NEWS | 6 ++++++ 8 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -39,7 +39,7 @@ Finally, you do have the option of :ref:`using 2to3 ` to translate Python 2 code into Python 3 code (with some manual help). This can take the form of branching your code and using 2to3 to start a Python 3 branch. You can -also have users perform the translation as installation time automatically so +also have users perform the translation at installation time automatically so that you only have to maintain a Python 2 codebase. Regardless of which approach you choose, porting is not as hard or @@ -234,7 +234,7 @@ ``b'py'[1:2]`` is ``'y'`` in Python 2 and ``b'y'`` in Python 3 (i.e., close enough). -You cannot concatenate bytes and strings in Python 3. But since in Python +You cannot concatenate bytes and strings in Python 3. But since Python 2 has bytes aliased to ``str``, it will succeed: ``b'a' + u'b'`` works in Python 2, but ``b'a' + 'b'`` in Python 3 is a :exc:`TypeError`. A similar issue also comes about when doing comparisons between bytes and strings. @@ -328,7 +328,7 @@ textual data, people have over the years been rather loose in their delineation of what ``str`` instances held text compared to bytes. In Python 3 you cannot be so care-free anymore and need to properly handle the difference. The key -handling this issue to make sure that **every** string literal in your +handling this issue is to make sure that **every** string literal in your Python 2 code is either syntactically of functionally marked as either bytes or text data. After this is done you then need to make sure your APIs are designed to either handle a specific type or made to be properly polymorphic. @@ -343,7 +343,7 @@ and then designating textual data with a ``u`` prefix or using the ``unicode_literals`` future statement. -If your project supports versions of Python pre-dating 2.6, then you should use +If your project supports versions of Python predating 2.6, then you should use the six_ project and its ``b()`` function to denote bytes literals. For text literals you can either use six's ``u()`` function or use a ``u`` prefix. @@ -439,7 +439,7 @@ There are two ways to solve this issue. One is to use a custom 2to3 fixer. The blog post at http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/ specifies how to do this. That will allow 2to3 to change all instances of ``def -__unicode(self): ...`` to ``def __str__(self): ...``. This does require you +__unicode(self): ...`` to ``def __str__(self): ...``. This does require that you define your ``__str__()`` method in Python 2 before your ``__unicode__()`` method. diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -156,7 +156,7 @@ there, you may wait forever for the reply, because the request may still be in your output buffer. -Now we come the major stumbling block of sockets - ``send`` and ``recv`` operate +Now we come to the major stumbling block of sockets - ``send`` and ``recv`` operate on the network buffers. They do not necessarily handle all the bytes you hand them (or expect from them), because their major focus is handling the network buffers. In general, they return when the associated network buffers have been @@ -167,7 +167,7 @@ When a ``recv`` returns 0 bytes, it means the other side has closed (or is in the process of closing) the connection. You will not receive any more data on this connection. Ever. You may be able to send data successfully; I'll talk -about that some on the next page. +more about this later. A protocol like HTTP uses a socket for only one transfer. The client sends a request, then reads a reply. That's it. The socket is discarded. This means that diff --git a/Lib/httplib.py b/Lib/httplib.py --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -748,7 +748,11 @@ line = response.fp.readline(_MAXLINE + 1) if len(line) > _MAXLINE: raise LineTooLong("header line") - if line == '\r\n': break + if not line: + # for sites which EOF without sending trailer + break + if line == '\r\n': + break def connect(self): diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1498,7 +1498,8 @@ raise ImportError, 'no Python documentation found for %r' % thing return object, thing else: - return thing, getattr(thing, '__name__', None) + name = getattr(thing, '__name__', None) + return thing, name if isinstance(name, str) else None def render_doc(thing, title='Python Library Documentation: %s', forceload=0): """Render text documentation, given an object or a path to an object.""" 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 @@ -249,6 +249,17 @@ result, doc_loc = get_pydoc_text(xml.etree) self.assertEqual(doc_loc, "", "MODULE DOCS incorrectly includes a link") + def test_non_str_name(self): + # issue14638 + # Treat illegal (non-str) name like no name + class A: + __name__ = 42 + class B: + pass + adoc = pydoc.render_doc(A()) + bdoc = pydoc.render_doc(B()) + self.assertEqual(adoc.replace("A", "B"), bdoc) + def test_not_here(self): missing_module = "test.i_am_not_here" result = run_pydoc(missing_module) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -150,7 +150,7 @@ thread.start_new_thread(task, ()) started.acquire() while thread._count() > c: - pass + time.sleep(0.01) self.assertIn("Traceback", stderr.getvalue()) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -774,6 +774,7 @@ Denis Severson Ian Seyer Ha Shao +Mark Shannon Richard Shapiro Bruce Sherwood Alexander Shigin diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,12 @@ Library ------- +- Issue #14638: pydoc now treats non-string __name__ values as if they + were missing, instead of raising an error. + +- Issue #13684: Fix httplib tunnel issue of infinite loops for certain sites + which send EOF without trailing \r\n. + - Issue #14308: Fix an exception when a "dummy" thread is in the threading module's active list after a fork(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 08:34:34 2012 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 24 Apr 2012 08:34:34 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Note_that_context_manager_shou?= =?utf8?q?ld_be_in_separate_classes_if_they_implement?= Message-ID: http://hg.python.org/peps/rev/4dc42ccf4a40 changeset: 4301:4dc42ccf4a40 user: Raymond Hettinger date: Mon Apr 23 23:34:26 2012 -0700 summary: Note that context manager should be in separate classes if they implement non-obvious behaviors. files: pep-0008.txt | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -837,6 +837,20 @@ # Will also catch KeyError raised by handle_value() return key_not_found(key) +- Context managers should be in separate classes whenever they do + something other than acquire and release resources. For example: + + Yes: with auto_commit_or_rollback(conn): + do_transaction(conn) + + No: with conn: + do_transaction(conn) + + The latter example doesn't provide any information to indicate that + the __enter__ and __exit__ methods are doing something other than + closing the connection after a transaction. Being explicit is + important in this case. + - Use string methods instead of the string module. String methods are always much faster and share the same API with -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 13:12:05 2012 From: python-checkins at python.org (eric.smith) Date: Tue, 24 Apr 2012 13:12:05 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Added_pointer_to_features/pep-?= =?utf8?q?420_branch=2E?= Message-ID: http://hg.python.org/peps/rev/0a478fe7bf9d changeset: 4302:0a478fe7bf9d user: Eric V. Smith date: Tue Apr 24 07:12:00 2012 -0400 summary: Added pointer to features/pep-420 branch. files: pep-0420.txt | 12 +++++++----- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -19,7 +19,7 @@ formulated. With the enhancement proposed here, the import machinery itself will construct the list of directories that make up the package. This PEP builds upon the work started in rejected PEPs 382 -and 402. +and 402. An implementation of this PEP is at [1]_. Terminology =========== @@ -162,10 +162,10 @@ ImportError would be raised. At PyCon 2012, we had a discussion about namespace packages at which -PEP 382 and PEP 402 were rejected, to be replaced by this PEP [1]_. +PEP 382 and PEP 402 were rejected, to be replaced by this PEP [2]_. Nick Coglan presented a list of his objections to this proposal -[2]_. They are: +[3]_. They are: * Implicit package directories go against the Zen of Python @@ -184,10 +184,12 @@ References ========== -.. [1] PyCon 2012 Namespace Package discussion outcome +.. [1] PEP 420 branch (http://hg.python.org/features/pep-420) + +.. [2] PyCon 2012 Namespace Package discussion outcome (http://mail.python.org/pipermail/import-sig/2012-March/000421.html) -.. [2] Nick Coglan's objection to the lack of marker files or directories +.. [3] Nick Coglan's objection to the lack of marker files or directories (http://mail.python.org/pipermail/import-sig/2012-March/000423.html) Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 13:57:01 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 24 Apr 2012 13:57:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Skip_long_repr_tests_when_t?= =?utf8?q?he_cached_pyc_file=27s_path_length_would_exceed_the?= Message-ID: http://hg.python.org/cpython/rev/9381e368b1ae changeset: 76516:9381e368b1ae parent: 76512:de0b6e0d8cb9 user: Antoine Pitrou date: Tue Apr 24 13:55:35 2012 +0200 summary: Skip long repr tests when the cached pyc file's path length would exceed the maximum Win32 path length. This should fix a failure on one of the XP buildbots. files: Lib/test/test_reprlib.py | 28 +++++++++++++++++++++++++--- 1 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_reprlib.py b/Lib/test/test_reprlib.py --- a/Lib/test/test_reprlib.py +++ b/Lib/test/test_reprlib.py @@ -3,6 +3,7 @@ Nick Mathewson """ +import imp import sys import os import shutil @@ -199,10 +200,11 @@ fp.write(text) class LongReprTest(unittest.TestCase): + longname = 'areallylongpackageandmodulenametotestreprtruncation' + def setUp(self): - longname = 'areallylongpackageandmodulenametotestreprtruncation' - self.pkgname = os.path.join(longname) - self.subpkgname = os.path.join(longname, longname) + self.pkgname = os.path.join(self.longname) + self.subpkgname = os.path.join(self.longname, self.longname) # Make the package and subpackage shutil.rmtree(self.pkgname, ignore_errors=True) os.mkdir(self.pkgname) @@ -232,7 +234,23 @@ os.remove(p) del sys.path[0] + def _check_path_limitations(self, module_name): + # base directory + source_path_len = len(self.here) + # a path separator + `longname` (twice) + source_path_len += 2 * (len(self.longname) + 1) + # a path separator + `module_name` + ".py" + source_path_len += len(module_name) + 1 + len(".py") + cached_path_len = source_path_len + len(imp.cache_from_source("x.py")) - len("x.py") + if os.name == 'nt' and cached_path_len >= 259: + # Under Windows, the max path len is 260 including C's terminating + # NUL character. + # (see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#maxpath) + self.skipTest("test paths too long (%d characters) for Windows' 260 character limit" + % cached_path_len) + def test_module(self): + self._check_path_limitations(self.pkgname) eq = self.assertEqual create_empty_file(os.path.join(self.subpkgname, self.pkgname + '.py')) importlib.invalidate_caches() @@ -242,6 +260,7 @@ eq(repr(sys), "") def test_type(self): + self._check_path_limitations('foo') eq = self.assertEqual write_file(os.path.join(self.subpkgname, 'foo.py'), '''\ class foo(object): @@ -258,6 +277,7 @@ pass def test_class(self): + self._check_path_limitations('bar') write_file(os.path.join(self.subpkgname, 'bar.py'), '''\ class bar: pass @@ -268,6 +288,7 @@ self.assertEqual(repr(bar.bar), "" % bar.__name__) def test_instance(self): + self._check_path_limitations('baz') write_file(os.path.join(self.subpkgname, 'baz.py'), '''\ class baz: pass @@ -279,6 +300,7 @@ "<%s.baz object at 0x" % baz.__name__)) def test_method(self): + self._check_path_limitations('qux') eq = self.assertEqual write_file(os.path.join(self.subpkgname, 'qux.py'), '''\ class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 14:09:23 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 24 Apr 2012 14:09:23 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Make_context_manager_example_l?= =?utf8?q?ikelier?= Message-ID: http://hg.python.org/peps/rev/8810c6f686f7 changeset: 4303:8810c6f686f7 user: Antoine Pitrou date: Tue Apr 24 14:08:00 2012 +0200 summary: Make context manager example likelier files: pep-0008.txt | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -837,14 +837,15 @@ # Will also catch KeyError raised by handle_value() return key_not_found(key) -- Context managers should be in separate classes whenever they do - something other than acquire and release resources. For example: +- Context managers should be invoked through separate functions or methods + whenever they do something other than acquire and release resources. + For example: - Yes: with auto_commit_or_rollback(conn): - do_transaction(conn) + Yes: with conn.begin_transaction(): + do_stuff_in_transaction(conn) No: with conn: - do_transaction(conn) + do_stuff_in_transaction(conn) The latter example doesn't provide any information to indicate that the __enter__ and __exit__ methods are doing something other than -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 16:34:00 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Apr 2012 16:34:00 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_fix_dict_gc_tracking_=28=23?= =?utf8?q?13903=29?= Message-ID: http://hg.python.org/cpython/rev/507a6703d6a3 changeset: 76517:507a6703d6a3 user: Benjamin Peterson date: Tue Apr 24 10:32:57 2012 -0400 summary: fix dict gc tracking (#13903) files: Objects/dictobject.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2022,6 +2022,8 @@ Py_XINCREF(value); split_copy->ma_values[i] = value; } + if (_PyObject_GC_IS_TRACKED(mp)) + _PyObject_GC_TRACK(split_copy); return (PyObject *)split_copy; } copy = PyDict_New(); @@ -2220,6 +2222,7 @@ return NULL; ep = find_empty_slot(mp, key, hash, &value_addr); } + MAINTAIN_TRACKING(mp, key, failobj); ep->me_key = key; ep->me_hash = hash; *value_addr = failobj; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 17:09:28 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Apr 2012 17:09:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_don=27t_use_a_s?= =?utf8?q?lot_wrapper_from_a_different_special_method_=28closes_=2314658?= =?utf8?q?=29?= Message-ID: http://hg.python.org/cpython/rev/971865f12377 changeset: 76518:971865f12377 branch: 3.2 parent: 76506:f7b002e5cac7 user: Benjamin Peterson date: Tue Apr 24 11:06:25 2012 -0400 summary: don't use a slot wrapper from a different special method (closes #14658) This also alters the fix to #11603. Specifically, setting __repr__ to object.__str__ now raises a recursion RuntimeError when str() or repr() is called instead of silently bypassing the recursion. I believe this behavior is more correct. files: Lib/test/test_descr.py | 10 +++++++++- Misc/NEWS | 6 ++++++ Objects/typeobject.c | 5 +++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4430,7 +4430,15 @@ pass Foo.__repr__ = Foo.__str__ foo = Foo() - str(foo) + self.assertRaises(RuntimeError, str, foo) + self.assertRaises(RuntimeError, repr, foo) + + def test_mixing_slot_wrappers(self): + class X(dict): + __setattr__ = dict.__setitem__ + x = X() + x.y = 42 + self.assertEqual(x["y"], 42) def test_cycle_through_dict(self): # See bug #1469629 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,12 @@ Core and Builtins ----------------- +- Issue #11603 (again): Setting __repr__ to __str__ now raises a RuntimeError + when repr() or str() is called on such an object. + +- Issue #14658: Fix binding a special method to a builtin implementation of a + special method with a different name. + - Issue #14630: Fix a memory access bug for instances of a subclass of int with value 0. diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2928,7 +2928,7 @@ unaryfunc f; f = Py_TYPE(self)->tp_repr; - if (f == NULL || f == object_str) + if (f == NULL) f = object_repr; return f(self); } @@ -5757,7 +5757,8 @@ } continue; } - if (Py_TYPE(descr) == &PyWrapperDescr_Type) { + if (Py_TYPE(descr) == &PyWrapperDescr_Type && + ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr = resolve_slotdups(type, p->name_strobj); if (tptr == NULL || tptr == ptr) generic = p->function; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 17:09:29 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Apr 2012 17:09:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?b?OiBtZXJnZSAzLjIgKCMxNDY1OCk=?= Message-ID: http://hg.python.org/cpython/rev/0c1c8f8955d8 changeset: 76519:0c1c8f8955d8 parent: 76517:507a6703d6a3 parent: 76518:971865f12377 user: Benjamin Peterson date: Tue Apr 24 11:09:20 2012 -0400 summary: merge 3.2 (#14658) files: Lib/test/test_descr.py | 10 +++++++++- Misc/NEWS | 6 ++++++ Objects/typeobject.c | 5 +++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4438,7 +4438,15 @@ pass Foo.__repr__ = Foo.__str__ foo = Foo() - str(foo) + self.assertRaises(RuntimeError, str, foo) + self.assertRaises(RuntimeError, repr, foo) + + def test_mixing_slot_wrappers(self): + class X(dict): + __setattr__ = dict.__setitem__ + x = X() + x.y = 42 + self.assertEqual(x["y"], 42) def test_slot_shadows_class_variable(self): with self.assertRaises(ValueError) as cm: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -14,6 +14,12 @@ their keys with other dictionaries. Classes take advantage of this to share their instance dictionary keys for improved memory and performance. +- Issue #11603 (again): Setting __repr__ to __str__ now raises a RuntimeError + when repr() or str() is called on such an object. + +- Issue #14658: Fix binding a special method to a builtin implementation of a + special method with a different name. + - Issue #14630: Fix a memory access bug for instances of a subclass of int with value 0. diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3035,7 +3035,7 @@ unaryfunc f; f = Py_TYPE(self)->tp_repr; - if (f == NULL || f == object_str) + if (f == NULL) f = object_repr; return f(self); } @@ -5879,7 +5879,8 @@ } continue; } - if (Py_TYPE(descr) == &PyWrapperDescr_Type) { + if (Py_TYPE(descr) == &PyWrapperDescr_Type && + ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr = resolve_slotdups(type, p->name_strobj); if (tptr == NULL || tptr == ptr) generic = p->function; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 17:10:30 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Apr 2012 17:10:30 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_don=27t_use_a_s?= =?utf8?q?lot_wrapper_from_a_different_special_method_=28closes_=2314658?= =?utf8?q?=29?= Message-ID: http://hg.python.org/cpython/rev/e3eda2d91e93 changeset: 76520:e3eda2d91e93 branch: 2.7 parent: 76515:6a60359556f9 user: Benjamin Peterson date: Tue Apr 24 11:06:25 2012 -0400 summary: don't use a slot wrapper from a different special method (closes #14658) This also alters the fix to #11603. Specifically, setting __repr__ to object.__str__ now raises a recursion RuntimeError when str() or repr() is called instead of silently bypassing the recursion. I believe this behavior is more correct. files: Lib/test/test_descr.py | 10 +++++++++- Misc/NEWS | 6 ++++++ Objects/typeobject.c | 5 +++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4591,7 +4591,15 @@ pass Foo.__repr__ = Foo.__str__ foo = Foo() - str(foo) + self.assertRaises(RuntimeError, str, foo) + self.assertRaises(RuntimeError, repr, foo) + + def test_mixing_slot_wrappers(self): + class X(dict): + __setattr__ = dict.__setitem__ + x = X() + x.y = 42 + self.assertEqual(x["y"], 42) def test_cycle_through_dict(self): # See bug #1469629 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,12 @@ Core and Builtins ----------------- +- Issue #11603 (again): Setting __repr__ to __str__ now raises a RuntimeError + when repr() or str() is called on such an object. + +- Issue #14658: Fix binding a special method to a builtin implementation of a + special method with a different name. + - Issue #14612: Fix jumping around with blocks by setting f_lineno. - Issue #13889: Check and (if necessary) set FPU control word before calling diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2996,7 +2996,7 @@ unaryfunc f; f = Py_TYPE(self)->tp_repr; - if (f == NULL || f == object_str) + if (f == NULL) f = object_repr; return f(self); } @@ -6143,7 +6143,8 @@ } continue; } - if (Py_TYPE(descr) == &PyWrapperDescr_Type) { + if (Py_TYPE(descr) == &PyWrapperDescr_Type && + ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr = resolve_slotdups(type, p->name_strobj); if (tptr == NULL || tptr == ptr) generic = p->function; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 17:38:44 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 17:38:44 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzNTg3?= =?utf8?q?=3A_use_the_right_RFC2617_name_for_WWW-Authenticate=3B_patch_by_?= =?utf8?q?Aaron?= Message-ID: http://hg.python.org/cpython/rev/4dda3000c932 changeset: 76521:4dda3000c932 branch: 2.7 user: Sandro Tosi date: Tue Apr 24 17:36:14 2012 +0200 summary: Issue #13587: use the right RFC2617 name for WWW-Authenticate; patch by Aaron Maenpaa files: Doc/howto/urllib2.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -439,12 +439,12 @@ When authentication is required, the server sends a header (as well as the 401 error code) requesting authentication. This specifies the authentication scheme -and a 'realm'. The header looks like : ``Www-authenticate: SCHEME +and a 'realm'. The header looks like : ``WWW-Authenticate: SCHEME realm="REALM"``. e.g. :: - Www-authenticate: Basic realm="cPanel Users" + WWW-Authenticate: Basic realm="cPanel Users" The client should then retry the request with the appropriate name and password -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 17:38:45 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 17:38:45 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzNTg3?= =?utf8?q?=3A_use_the_right_RFC2617_name_for_WWW-Authenticate=3B_patch_by_?= =?utf8?q?Aaron?= Message-ID: http://hg.python.org/cpython/rev/01abffa8842a changeset: 76522:01abffa8842a branch: 3.2 parent: 76518:971865f12377 user: Sandro Tosi date: Tue Apr 24 17:36:41 2012 +0200 summary: Issue #13587: use the right RFC2617 name for WWW-Authenticate; patch by Aaron Maenpaa files: Doc/howto/urllib2.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -448,12 +448,12 @@ When authentication is required, the server sends a header (as well as the 401 error code) requesting authentication. This specifies the authentication scheme -and a 'realm'. The header looks like : ``Www-authenticate: SCHEME +and a 'realm'. The header looks like : ``WWW-Authenticate: SCHEME realm="REALM"``. e.g. :: - Www-authenticate: Basic realm="cPanel Users" + WWW-Authenticate: Basic realm="cPanel Users" The client should then retry the request with the appropriate name and password -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 17:38:45 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 17:38:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2313587=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/798b9714777d changeset: 76523:798b9714777d parent: 76519:0c1c8f8955d8 parent: 76522:01abffa8842a user: Sandro Tosi date: Tue Apr 24 17:37:02 2012 +0200 summary: Issue #13587: merge with 3.2 files: Doc/howto/urllib2.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -455,12 +455,12 @@ When authentication is required, the server sends a header (as well as the 401 error code) requesting authentication. This specifies the authentication scheme -and a 'realm'. The header looks like : ``Www-authenticate: SCHEME +and a 'realm'. The header looks like : ``WWW-Authenticate: SCHEME realm="REALM"``. e.g. :: - Www-authenticate: Basic realm="cPanel Users" + WWW-Authenticate: Basic realm="cPanel Users" The client should then retry the request with the appropriate name and password -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 18:13:59 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 18:13:59 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzNDc4?= =?utf8?q?=3A_document_timeit=2Edefault=5Ftimer=28=29?= Message-ID: http://hg.python.org/cpython/rev/86b927859155 changeset: 76524:86b927859155 branch: 2.7 parent: 76521:4dda3000c932 user: Sandro Tosi date: Tue Apr 24 18:11:29 2012 +0200 summary: Issue #13478: document timeit.default_timer() files: Doc/library/timeit.rst | 22 ++++++++++++++-------- 1 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -101,9 +101,19 @@ timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit() -Starting with version 2.6, the module also defines two convenience functions: +The module also defines three convenience functions: +.. function:: default_timer() + + Define a default timer, in a platform specific manner. On Windows, + :func:`time.clock` has microsecond granularity but :func:`time.time`'s + granularity is 1/60th of a second; on Unix, :func:`time.clock` has 1/100th of + a second granularity and :func:`time.time` is much more precise. On either + platform, :func:`default_timer` measures wall clock time, not the CPU + time. This means that other processes running on the same computer may + interfere with the timing. + .. function:: repeat(stmt[, setup[, timer[, repeat=3 [, number=1000000]]]]) Create a :class:`Timer` instance with the given statement, setup code and timer @@ -168,13 +178,9 @@ If :option:`-n` is not given, a suitable number of loops is calculated by trying successive powers of 10 until the total time is at least 0.2 seconds. -The default timer function is platform dependent. On Windows, -:func:`time.clock` has microsecond granularity but :func:`time.time`'s -granularity is 1/60th of a second; on Unix, :func:`time.clock` has 1/100th of a -second granularity and :func:`time.time` is much more precise. On either -platform, the default timer functions measure wall clock time, not the CPU time. -This means that other processes running on the same computer may interfere with -the timing. The best thing to do when accurate timing is necessary is to repeat +:func:`default_timer` measurations can be affected by other programs running on +the same machine, so +the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The :option:`-r` option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use :func:`time.clock` to measure CPU time. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 18:14:00 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 18:14:00 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzNDc4?= =?utf8?q?=3A_document_timeit=2Edefault=5Ftimer=28=29?= Message-ID: http://hg.python.org/cpython/rev/8165b59a4000 changeset: 76525:8165b59a4000 branch: 3.2 parent: 76522:01abffa8842a user: Sandro Tosi date: Tue Apr 24 18:11:46 2012 +0200 summary: Issue #13478: document timeit.default_timer() files: Doc/library/timeit.rst | 24 ++++++++++++++++-------- 1 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -99,7 +99,19 @@ timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit() -The module also defines two convenience functions: +The module also defines three convenience functions: + + +.. function:: default_timer() + + Define a default timer, in a platform specific manner. On Windows, + :func:`time.clock` has microsecond granularity but :func:`time.time`'s + granularity is 1/60th of a second; on Unix, :func:`time.clock` has 1/100th of + a second granularity and :func:`time.time` is much more precise. On either + platform, :func:`default_timer` measures wall clock time, not the CPU + time. This means that other processes running on the same computer may + interfere with the timing. + .. function:: repeat(stmt='pass', setup='pass', timer=, repeat=3, number=1000000) @@ -161,13 +173,9 @@ If :option:`-n` is not given, a suitable number of loops is calculated by trying successive powers of 10 until the total time is at least 0.2 seconds. -The default timer function is platform dependent. On Windows, -:func:`time.clock` has microsecond granularity but :func:`time.time`'s -granularity is 1/60th of a second; on Unix, :func:`time.clock` has 1/100th of a -second granularity and :func:`time.time` is much more precise. On either -platform, the default timer functions measure wall clock time, not the CPU time. -This means that other processes running on the same computer may interfere with -the timing. The best thing to do when accurate timing is necessary is to repeat +:func:`default_timer` measurations can be affected by other programs running on +the same machine, so +the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The :option:`-r` option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use :func:`time.clock` to measure CPU time. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 18:14:01 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 18:14:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2313478=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/e43ba06da592 changeset: 76526:e43ba06da592 parent: 76523:798b9714777d parent: 76525:8165b59a4000 user: Sandro Tosi date: Tue Apr 24 18:12:13 2012 +0200 summary: Issue #13478: merge with 3.2 files: Doc/library/timeit.rst | 24 ++++++++++++++++-------- 1 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -99,7 +99,19 @@ timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit() -The module also defines two convenience functions: +The module also defines three convenience functions: + + +.. function:: default_timer() + + Define a default timer, in a platform specific manner. On Windows, + :func:`time.clock` has microsecond granularity but :func:`time.time`'s + granularity is 1/60th of a second; on Unix, :func:`time.clock` has 1/100th of + a second granularity and :func:`time.time` is much more precise. On either + platform, :func:`default_timer` measures wall clock time, not the CPU + time. This means that other processes running on the same computer may + interfere with the timing. + .. function:: repeat(stmt='pass', setup='pass', timer=, repeat=3, number=1000000) @@ -161,13 +173,9 @@ If :option:`-n` is not given, a suitable number of loops is calculated by trying successive powers of 10 until the total time is at least 0.2 seconds. -The default timer function is platform dependent. On Windows, -:func:`time.clock` has microsecond granularity but :func:`time.time`'s -granularity is 1/60th of a second; on Unix, :func:`time.clock` has 1/100th of a -second granularity and :func:`time.time` is much more precise. On either -platform, the default timer functions measure wall clock time, not the CPU time. -This means that other processes running on the same computer may interfere with -the timing. The best thing to do when accurate timing is necessary is to repeat +:func:`default_timer` measurations can be affected by other programs running on +the same machine, so +the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The :option:`-r` option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use :func:`time.clock` to measure CPU time. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 18:41:34 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 18:41:34 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NTU0?= =?utf8?q?=3A_correct_example_for_captured=5Fstdout=28=29?= Message-ID: http://hg.python.org/cpython/rev/22767284de99 changeset: 76527:22767284de99 branch: 2.7 parent: 76524:86b927859155 user: Sandro Tosi date: Tue Apr 24 18:38:59 2012 +0200 summary: Issue #14554: correct example for captured_stdout() files: Doc/library/test.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -380,7 +380,7 @@ with captured_stdout() as s: print "hello" - assert s.getvalue() == "hello" + assert s.getvalue() == "hello\n" .. versionadded:: 2.6 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 18:41:35 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 18:41:35 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NTU0?= =?utf8?q?=3A_correct_example_for_captured=5Fstdout=28=29=3B_patch_by_Tshe?= =?utf8?q?pang?= Message-ID: http://hg.python.org/cpython/rev/d1ba0421d65f changeset: 76528:d1ba0421d65f branch: 3.2 parent: 76525:8165b59a4000 user: Sandro Tosi date: Tue Apr 24 18:39:24 2012 +0200 summary: Issue #14554: correct example for captured_stdout(); patch by Tshepang Lekhonkhobe files: Doc/library/test.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -362,7 +362,7 @@ with captured_stdout() as s: print("hello") - assert s.getvalue() == "hello" + assert s.getvalue() == "hello\n" .. function:: import_module(name, deprecated=False) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 18:41:36 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 18:41:36 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314554=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/6f41f8ed87c8 changeset: 76529:6f41f8ed87c8 parent: 76526:e43ba06da592 parent: 76528:d1ba0421d65f user: Sandro Tosi date: Tue Apr 24 18:39:53 2012 +0200 summary: Issue #14554: merge with 3.2 files: Doc/library/test.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -372,7 +372,7 @@ with captured_stdout() as s: print("hello") - assert s.getvalue() == "hello" + assert s.getvalue() == "hello\n" .. function:: temp_cwd(name='tempcwd', quiet=False, path=None) -- Repository URL: http://hg.python.org/cpython From jimjjewett at gmail.com Tue Apr 24 18:56:50 2012 From: jimjjewett at gmail.com (Jim Jewett) Date: Tue, 24 Apr 2012 12:56:50 -0400 Subject: [Python-checkins] peps: Note that ImportError will no longer be raised due to a missing __init__.py In-Reply-To: References: Message-ID: On Thu, Apr 19, 2012 at 18:56, eric.smith wrote: > +Note that an ImportError will no longer be raised for a directory > +lacking an ``__init__.py`` file. Such a directory will now be imported > +as a namespace package, whereas in prior Python versions an > +ImportError would be raised. Given that there is no way to modify the __path__ of a namespace package (short of restarting python?), *should* it be an error if there is exactly one directory? Or is that just a case of "other tools out there, didn't happen to install them"? -jJ From eric at trueblade.com Tue Apr 24 19:02:30 2012 From: eric at trueblade.com (Eric Smith) Date: Tue, 24 Apr 2012 13:02:30 -0400 (EDT) Subject: [Python-checkins] peps: Note that ImportError will no longer be raised due to a missing __init__.py In-Reply-To: References: Message-ID: > On Thu, Apr 19, 2012 at 18:56, eric.smith wrote: > >> +Note that an ImportError will no longer be raised for a directory >> +lacking an ``__init__.py`` file. Such a directory will now be imported >> +as a namespace package, whereas in prior Python versions an >> +ImportError would be raised. > > Given that there is no way to modify the __path__ of a namespace > package (short of restarting python?), *should* it be an error if > there is exactly one directory? > > Or is that just a case of "other tools out there, didn't happen to > install them"? Right. If I just install zope.interfaces and no other zope packages, that shouldn't be an error. Eric. From python-checkins at python.org Tue Apr 24 19:06:21 2012 From: python-checkins at python.org (eric.smith) Date: Tue, 24 Apr 2012 19:06:21 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Update_section_on_impact_to_fi?= =?utf8?q?nders=2E?= Message-ID: http://hg.python.org/peps/rev/3c0c053d8cf5 changeset: 4304:3c0c053d8cf5 user: Eric V. Smith date: Tue Apr 24 13:05:25 2012 -0400 summary: Update section on impact to finders. files: pep-0420.txt | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -144,7 +144,14 @@ Impact on Import Finders and Loaders ------------------------------------ -To be determined in the sample implementation. +PEP 302 defines "finders" that are called to search path +elements. These finders' ``find_module`` methods currently return +either a "loader" object or None. For a finder to contribute to +namespace packages, ``find_module`` will return a third type: a +string. This is the string that will be recorded and later used as a +component of the namespace module's __path__, as described above. + +[Consider Brett's idea to pass NamespaceLoader in to PathFinder] Discussion ========== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Apr 24 19:14:38 2012 From: python-checkins at python.org (martin.v.loewis) Date: Tue, 24 Apr 2012 19:14:38 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Account_for_shared_keys_in_?= =?utf8?b?dHlwZSdzIF9fc2l6ZW9mX18gKCMxMzkwMyku?= Message-ID: http://hg.python.org/cpython/rev/b044e0568be2 changeset: 76530:b044e0568be2 user: Martin v. Loewis date: Tue Apr 24 19:13:57 2012 +0200 summary: Account for shared keys in type's __sizeof__ (#13903). files: Include/dictobject.h | 1 + Lib/test/test_sys.py | 12 +++++++++--- Objects/dictobject.c | 23 ++++++++++++----------- Objects/typeobject.c | 18 ++++++++++++++++++ 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -75,6 +75,7 @@ PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); +Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); #define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) PyAPI_FUNC(int) PyDict_ClearFreeList(void); diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -829,13 +829,19 @@ check((), size(vh)) check((1,2,3), size(vh) + 3*self.P) # type + # static type: PyTypeObject + s = size(vh + 'P2P15Pl4PP9PP11PI') + check(int, s) # (PyTypeObject + PyNumberMethods + PyMappingMethods + - # PySequenceMethods + PyBufferProcs) - s = size(vh + 'P2P15Pl4PP9PP11PIP') + size('16Pi17P 3P 10P 2P 3P') - check(int, s) + # PySequenceMethods + PyBufferProcs + 4P) + s = size(vh + 'P2P15Pl4PP9PP11PI') + size('34P 3P 10P 2P 4P') + # Separate block for PyDictKeysObject with 4 entries + s += size("PPPP") + 4*size("PPP") # class class newstyleclass(object): pass check(newstyleclass, s) + # dict with shared keys + check(newstyleclass().__dict__, size(h+"PPP4P")) # unicode # each tuple contains a string and its expected character size # don't put any static strings here, as they may contain diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2398,22 +2398,23 @@ static PyObject * dict_sizeof(PyDictObject *mp) { - Py_ssize_t size; - double res, keys_size; + Py_ssize_t size, res; size = DK_SIZE(mp->ma_keys); res = sizeof(PyDictObject); if (mp->ma_values) res += size * sizeof(PyObject*); - /* Count our share of the keys object -- with rounding errors. */ - keys_size = sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry); - /* If refcnt > 1, then one count is (probably) held by a type */ - /* XXX This is somewhat approximate :) */ - if (mp->ma_keys->dk_refcnt < 3) - res += keys_size; - else - res += keys_size / (mp->ma_keys->dk_refcnt - 1); - return PyFloat_FromDouble(res); + /* If the dictionary is split, the keys portion is accounted-for + in the type object. */ + if (mp->ma_keys->dk_refcnt == 1) + res += sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry); + return PyLong_FromSsize_t(res); +} + +Py_ssize_t +_PyDict_KeysSize(PyDictKeysObject *keys) +{ + return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry); } PyDoc_STRVAR(contains__doc__, diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2730,6 +2730,22 @@ return result; } +static PyObject* +type_sizeof(PyObject *self, PyObject *args_unused) +{ + Py_ssize_t size; + PyTypeObject *type = (PyTypeObject*)self; + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + PyHeapTypeObject* et = (PyHeapTypeObject*)type; + size = sizeof(PyHeapTypeObject); + if (et->ht_cached_keys) + size += _PyDict_KeysSize(et->ht_cached_keys); + } + else + size = sizeof(PyTypeObject); + return PyLong_FromSsize_t(size); +} + static PyMethodDef type_methods[] = { {"mro", (PyCFunction)mro_external, METH_NOARGS, PyDoc_STR("mro() -> list\nreturn a type's method resolution order")}, @@ -2745,6 +2761,8 @@ PyDoc_STR("__subclasscheck__() -> bool\ncheck if a class is a subclass")}, {"__dir__", type_dir, METH_NOARGS, PyDoc_STR("__dir__() -> list\nspecialized __dir__ implementation for types")}, + {"__sizeof__", type_sizeof, METH_NOARGS, + "__sizeof__() -> int\nreturn memory consumption of the type object"}, {0} }; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 19:17:45 2012 From: python-checkins at python.org (georg.brandl) Date: Tue, 24 Apr 2012 19:17:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_location_of_versionadde?= =?utf8?q?ds_and_empty_lines=2E?= Message-ID: http://hg.python.org/cpython/rev/224402f3ede4 changeset: 76531:224402f3ede4 user: Georg Brandl date: Tue Apr 24 19:16:24 2012 +0200 summary: Fix location of versionaddeds and empty lines. files: Doc/c-api/exceptions.rst | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -143,7 +143,7 @@ state temporarily. Use :c:func:`PyErr_SetExcInfo` to restore or clear the exception state. -.. versionadded:: 3.3 + .. versionadded:: 3.3 .. c:function:: void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) @@ -161,7 +161,7 @@ state temporarily. Use :c:func:`PyErr_GetExcInfo` to read the exception state. -.. versionadded:: 3.3 + .. versionadded:: 3.3 .. c:function:: void PyErr_SetString(PyObject *type, const char *message) @@ -264,6 +264,7 @@ Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, with an additional parameter specifying the exception type to be raised. Availability: Windows. + .. c:function:: PyObject* PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) This is a convenience function to raise :exc:`ImportError`. *msg* will be @@ -273,6 +274,7 @@ .. versionadded:: 3.3 + .. c:function:: void PyErr_SyntaxLocationEx(char *filename, int lineno, int col_offset) Set file, line, and offset information for the current exception. If the @@ -281,7 +283,7 @@ is a :exc:`SyntaxError`. *filename* is decoded from the filesystem encoding (:func:`sys.getfilesystemencoding`). -.. versionadded:: 3.2 + .. versionadded:: 3.2 .. c:function:: void PyErr_SyntaxLocation(char *filename, int lineno) @@ -354,6 +356,7 @@ .. versionadded:: 3.2 + .. c:function:: int PyErr_CheckSignals() .. index:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 19:48:09 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 19:48:09 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NDQ4?= =?utf8?q?=3A_mention_pytz=3B_patch_by_Andrew_Svetlov?= Message-ID: http://hg.python.org/cpython/rev/e0e421133d0f changeset: 76532:e0e421133d0f branch: 2.7 parent: 76527:22767284de99 user: Sandro Tosi date: Tue Apr 24 19:43:33 2012 +0200 summary: Issue #14448: mention pytz; patch by Andrew Svetlov files: Doc/library/datetime.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1521,6 +1521,14 @@ other fixed-offset :class:`tzinfo` subclass (such as a class representing only EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)). +.. seealso:: + + `pytz `_ + The Standard Library has no :class:`tzinfo` instances except for UTC, but + it exists a third-party library which brings Olson timezone database to + Python: `pytz`. + + `pytz` contains up-to-date information and its usage is recommended. .. _strftime-strptime-behavior: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 19:48:10 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 19:48:10 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NDQ4?= =?utf8?q?=3A_mention_pytz=3B_patch_by_Andrew_Svetlov?= Message-ID: http://hg.python.org/cpython/rev/3aec41794584 changeset: 76533:3aec41794584 branch: 3.2 parent: 76528:d1ba0421d65f user: Sandro Tosi date: Tue Apr 24 19:46:06 2012 +0200 summary: Issue #14448: mention pytz; patch by Andrew Svetlov files: Doc/library/datetime.rst | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1518,7 +1518,6 @@ .. literalinclude:: ../includes/tzinfo-examples.py - Note that there are unavoidable subtleties twice per year in a :class:`tzinfo` subclass accounting for both standard and daylight time, at the DST transition points. For concreteness, consider US Eastern (UTC -0500), where EDT begins the @@ -1558,6 +1557,15 @@ or any other fixed-offset :class:`tzinfo` subclass (such as a class representing only EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)). +.. seealso:: + + `pytz `_ + The Standard Library has no :class:`tzinfo` instances except for UTC, but + it exists a third-party library which brings Olson timezone database to + Python: `pytz`. + + `pytz` contains up-to-date information and its usage is recommended. + .. _datetime-timezone: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 19:48:11 2012 From: python-checkins at python.org (sandro.tosi) Date: Tue, 24 Apr 2012 19:48:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314448=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/b46fa7bc6710 changeset: 76534:b46fa7bc6710 parent: 76531:224402f3ede4 parent: 76533:3aec41794584 user: Sandro Tosi date: Tue Apr 24 19:46:29 2012 +0200 summary: Issue #14448: merge with 3.2 files: Doc/library/datetime.rst | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1557,7 +1557,6 @@ .. literalinclude:: ../includes/tzinfo-examples.py - Note that there are unavoidable subtleties twice per year in a :class:`tzinfo` subclass accounting for both standard and daylight time, at the DST transition points. For concreteness, consider US Eastern (UTC -0500), where EDT begins the @@ -1597,6 +1596,15 @@ or any other fixed-offset :class:`tzinfo` subclass (such as a class representing only EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)). +.. seealso:: + + `pytz `_ + The Standard Library has no :class:`tzinfo` instances except for UTC, but + it exists a third-party library which brings Olson timezone database to + Python: `pytz`. + + `pytz` contains up-to-date information and its usage is recommended. + .. _datetime-timezone: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 20:44:24 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Apr 2012 20:44:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_distiguish_between_refusing?= =?utf8?q?_to_creating_shared_keys_and_error_=28=2313903=29?= Message-ID: http://hg.python.org/cpython/rev/5d5b72a71898 changeset: 76535:5d5b72a71898 user: Benjamin Peterson date: Tue Apr 24 14:44:18 2012 -0400 summary: distiguish between refusing to creating shared keys and error (#13903) files: Lib/test/test_dict.py | 7 +++++++ Objects/dictobject.c | 11 +++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -889,6 +889,13 @@ self.assertEqual(f.msg, getattr(f, _str('msg'))) self.assertEqual(f.msg, f.__dict__[_str('msg')]) + def test_object_set_item_single_instance_non_str_key(self): + class Foo: pass + f = Foo() + f.__dict__[1] = 1 + f.a = 'a' + self.assertEqual(f.__dict__, {1:1, 'a':'a'}) + from test import mapping_tests class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -966,6 +966,8 @@ return 0; } +/* Returns NULL if unable to split table. + * A NULL return does not necessarily indicate an error */ static PyDictKeysObject * make_keys_shared(PyObject *op) { @@ -973,7 +975,8 @@ Py_ssize_t size; PyDictObject *mp = (PyDictObject *)op; - assert(PyDict_CheckExact(op)); + if (!PyDict_CheckExact(op)) + return NULL; if (!_PyDict_HasSplitTable(mp)) { PyDictKeyEntry *ep0; PyObject **values; @@ -3694,14 +3697,14 @@ res = PyDict_SetItem(dict, key, value); if (cached != ((PyDictObject *)dict)->ma_keys) { /* Either update tp->ht_cached_keys or delete it */ - if (cached->dk_refcnt == 1 && PyDict_CheckExact(dict)) { + if (cached->dk_refcnt == 1) { CACHED_KEYS(tp) = make_keys_shared(dict); - if (CACHED_KEYS(tp) == NULL) - return -1; } else { CACHED_KEYS(tp) = NULL; } DK_DECREF(cached); + if (CACHED_KEYS(tp) == NULL && PyErr_Occurred()) + return -1; } } } else { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 21:00:48 2012 From: python-checkins at python.org (jesus.cea) Date: Tue, 24 Apr 2012 21:00:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314661=3A_posix_mod?= =?utf8?q?ule=3A_add_O=5FEXEC=2C_O=5FSEARCH=2C_O=5FTTY=5FINIT?= Message-ID: http://hg.python.org/cpython/rev/34de406f566d changeset: 76536:34de406f566d user: Jesus Cea date: Tue Apr 24 20:44:40 2012 +0200 summary: Issue #14661: posix module: add O_EXEC, O_SEARCH, O_TTY_INIT files: Modules/posixmodule.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11176,6 +11176,15 @@ #ifdef O_EXLOCK if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1; #endif +#ifdef O_EXEC + if (ins(d, "O_EXEC", (long)O_EXEC)) return -1; +#endif +#ifdef O_SEARCH + if (ins(d, "O_SEARCH", (long)O_SEARCH)) return -1; +#endif +#ifdef O_TTY_INIT + if (ins(d, "O_TTY_INIT", (long)O_TTY_INIT)) return -1; +#endif #ifdef PRIO_PROCESS if (ins(d, "PRIO_PROCESS", (long)PRIO_PROCESS)) return -1; #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 21:00:49 2012 From: python-checkins at python.org (jesus.cea) Date: Tue, 24 Apr 2012 21:00:49 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Closes_Issue_=2314661=3A_po?= =?utf8?q?six_module=3A_add_O=5FEXEC=2C_O=5FSEARCH=2C_O=5FTTY=5FINIT_=28I_?= =?utf8?q?add_some?= Message-ID: http://hg.python.org/cpython/rev/2023f48b32b6 changeset: 76537:2023f48b32b6 user: Jesus Cea date: Tue Apr 24 20:59:17 2012 +0200 summary: Closes Issue #14661: posix module: add O_EXEC, O_SEARCH, O_TTY_INIT (I add some Solaris constants too) files: Modules/posixmodule.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11167,6 +11167,9 @@ #ifdef O_TEXT if (ins(d, "O_TEXT", (long)O_TEXT)) return -1; #endif +#ifdef O_XATTR + if (ins(d, "O_XATTR", (long)O_XATTR)) return -1; +#endif #ifdef O_LARGEFILE if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1; #endif @@ -11197,6 +11200,9 @@ #ifdef O_CLOEXEC if (ins(d, "O_CLOEXEC", (long)O_CLOEXEC)) return -1; #endif +#ifdef O_ACCMODE + if (ins(d, "O_ACCMODE", (long)O_ACCMODE)) return -1; +#endif /* posix - constants for *at functions */ #ifdef AT_SYMLINK_NOFOLLOW if (ins(d, "AT_SYMLINK_NOFOLLOW", (long)AT_SYMLINK_NOFOLLOW)) return -1; @@ -11262,6 +11268,10 @@ /* Do not follow links. */ if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1; #endif +#ifdef O_NOLINKS + /* Fails if link count of the named file is greater than 1 */ + if (ins(d, "O_NOLINKS", (long)O_NOLINKS)) return -1; +#endif #ifdef O_NOATIME /* Do not update the access time. */ if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 21:09:34 2012 From: python-checkins at python.org (lars.gustaebel) Date: Tue, 24 Apr 2012 21:09:34 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0MTYw?= =?utf8?q?=3A_TarFile=2Eextractfile=28=29_failed_to_resolve_symbolic_links?= Message-ID: http://hg.python.org/cpython/rev/0adf4fd8df83 changeset: 76538:0adf4fd8df83 branch: 3.2 parent: 76533:3aec41794584 user: Lars Gust?bel date: Tue Apr 24 21:04:40 2012 +0200 summary: Issue #14160: TarFile.extractfile() failed to resolve symbolic links when the links were not located in an archive subdirectory. files: Lib/tarfile.py | 2 +- Lib/test/test_tarfile.py | 3 +++ Lib/test/testtar.tar | Bin Misc/NEWS | 3 +++ 4 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2496,7 +2496,7 @@ """ if tarinfo.issym(): # Always search the entire archive. - linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + linkname = "/".join(filter(None, (os.path.dirname(tarinfo.name), tarinfo.linkname))) limit = None else: # Search the archive before the link, because a hard link is diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -166,6 +166,9 @@ def test_fileobj_symlink2(self): self._test_fileobj_link("./ustar/linktest2/symtype", "ustar/linktest1/regtype") + def test_issue14160(self): + self._test_fileobj_link("symtype2", "ustar/regtype") + class CommonReadTest(ReadTest): diff --git a/Lib/test/testtar.tar b/Lib/test/testtar.tar index b93210453d132cf0db07ab26cb50d06f83ee579a..bb9345373e9701b01f16b70844445dfe1863abc6 GIT binary patch [stripped] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,9 @@ Library ------- +- Issue #14160: TarFile.extractfile() failed to resolve symbolic links when + the links were not located in an archive subdirectory. + - Issue #14638: pydoc now treats non-string __name__ values as if they were missing, instead of raising an error. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 21:09:35 2012 From: python-checkins at python.org (lars.gustaebel) Date: Tue, 24 Apr 2012 21:09:35 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_with_3=2E2=3A_Issue_=2314160=3A_TarFile=2Eextractfile?= =?utf8?q?=28=29_failed_to_resolve_symbolic?= Message-ID: http://hg.python.org/cpython/rev/38df99776901 changeset: 76539:38df99776901 parent: 76537:2023f48b32b6 parent: 76538:0adf4fd8df83 user: Lars Gust?bel date: Tue Apr 24 21:09:17 2012 +0200 summary: Merge with 3.2: Issue #14160: TarFile.extractfile() failed to resolve symbolic links when the links were not located in an archive subdirectory. files: Lib/tarfile.py | 2 +- Lib/test/test_tarfile.py | 3 +++ Lib/test/testtar.tar | Bin Misc/NEWS | 3 +++ 4 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2481,7 +2481,7 @@ """ if tarinfo.issym(): # Always search the entire archive. - linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + linkname = "/".join(filter(None, (os.path.dirname(tarinfo.name), tarinfo.linkname))) limit = None else: # Search the archive before the link, because a hard link is diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -171,6 +171,9 @@ def test_fileobj_symlink2(self): self._test_fileobj_link("./ustar/linktest2/symtype", "ustar/linktest1/regtype") + def test_issue14160(self): + self._test_fileobj_link("symtype2", "ustar/regtype") + class CommonReadTest(ReadTest): diff --git a/Lib/test/testtar.tar b/Lib/test/testtar.tar index b93210453d132cf0db07ab26cb50d06f83ee579a..bb9345373e9701b01f16b70844445dfe1863abc6 GIT binary patch [stripped] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -71,6 +71,9 @@ Library ------- +- Issue #14160: TarFile.extractfile() failed to resolve symbolic links when + the links were not located in an archive subdirectory. + - Issue #14638: pydoc now treats non-string __name__ values as if they were missing, instead of raising an error. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Apr 24 22:42:44 2012 From: python-checkins at python.org (lars.gustaebel) Date: Tue, 24 Apr 2012 22:42:44 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0MTYw?= =?utf8?q?=3A_TarFile=2Eextractfile=28=29_failed_to_resolve_symbolic_links?= =?utf8?q?_when?= Message-ID: http://hg.python.org/cpython/rev/aff14bea5596 changeset: 76540:aff14bea5596 branch: 2.7 parent: 76532:e0e421133d0f user: Lars Gust?bel date: Tue Apr 24 22:42:08 2012 +0200 summary: Issue #14160: TarFile.extractfile() failed to resolve symbolic links when the links were not located in an archive subdirectory. files: Lib/tarfile.py | 2 +- Lib/test/test_tarfile.py | 3 +++ Lib/test/testtar.tar | Bin Misc/NEWS | 3 +++ 4 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2397,7 +2397,7 @@ """ if tarinfo.issym(): # Always search the entire archive. - linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + linkname = "/".join(filter(None, (os.path.dirname(tarinfo.name), tarinfo.linkname))) limit = None else: # Search the archive before the link, because a hard link is diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -154,6 +154,9 @@ def test_fileobj_symlink2(self): self._test_fileobj_link("./ustar/linktest2/symtype", "ustar/linktest1/regtype") + def test_issue14160(self): + self._test_fileobj_link("symtype2", "ustar/regtype") + class CommonReadTest(ReadTest): diff --git a/Lib/test/testtar.tar b/Lib/test/testtar.tar index bac0e2628f35243f236db2fac82737882699b2f0..440182a437da84ef3d61d8cbc0f4209254615b37 GIT binary patch [stripped] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,9 @@ Library ------- +- Issue #14160: TarFile.extractfile() failed to resolve symbolic links when + the links were not located in an archive subdirectory. + - Issue #14638: pydoc now treats non-string __name__ values as if they were missing, instead of raising an error. -- Repository URL: http://hg.python.org/cpython From victor.stinner at gmail.com Tue Apr 24 22:49:08 2012 From: victor.stinner at gmail.com (Victor Stinner) Date: Tue, 24 Apr 2012 22:49:08 +0200 Subject: [Python-checkins] cpython: Closes Issue #14661: posix module: add O_EXEC, O_SEARCH, O_TTY_INIT (I add some In-Reply-To: References: Message-ID: 2012/4/24 jesus.cea : > http://hg.python.org/cpython/rev/2023f48b32b6 > changeset: ? 76537:2023f48b32b6 > user: ? ? ? ?Jesus Cea > date: ? ? ? ?Tue Apr 24 20:59:17 2012 +0200 > summary: > ?Closes Issue #14661: posix module: add O_EXEC, O_SEARCH, O_TTY_INIT (I add some Solaris constants too) Don't you want to document these new constants in Doc/library/os.rst? Victor From python-checkins at python.org Tue Apr 24 22:58:22 2012 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 24 Apr 2012 22:58:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=234892=3A_multiproce?= =?utf8?q?ssing_Connections_can_now_be_transferred_over?= Message-ID: http://hg.python.org/cpython/rev/08d4c2fe51ea changeset: 76541:08d4c2fe51ea parent: 76539:38df99776901 user: Antoine Pitrou date: Tue Apr 24 22:56:57 2012 +0200 summary: Issue #4892: multiprocessing Connections can now be transferred over multiprocessing Connections. Patch by Richard Oudkerk (sbt). files: Doc/library/multiprocessing.rst | 4 + Lib/multiprocessing/__init__.py | 4 +- Lib/multiprocessing/connection.py | 24 +- Lib/multiprocessing/forking.py | 19 - Lib/multiprocessing/reduction.py | 311 ++++++++++------- Lib/test/test_multiprocessing.py | 105 ++++-- Misc/NEWS | 3 + Modules/_winapi.c | 4 + 8 files changed, 282 insertions(+), 192 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -832,6 +832,10 @@ raised and the complete message is available as ``e.args[0]`` where ``e`` is the exception instance. + .. versionchanged:: 3.3 + Connection objects themselves can now be transferred between processes + using :meth:`Connection.send` and :meth:`Connection.recv`. + For example: diff --git a/Lib/multiprocessing/__init__.py b/Lib/multiprocessing/__init__.py --- a/Lib/multiprocessing/__init__.py +++ b/Lib/multiprocessing/__init__.py @@ -161,7 +161,9 @@ ''' Install support for sending connections and sockets between processes ''' - from multiprocessing import reduction + # This is undocumented. In previous versions of multiprocessing + # its only effect was to make socket objects inheritable on Windows. + import multiprocessing.connection # # Definitions depending on native semaphores diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -50,6 +50,7 @@ from multiprocessing import current_process, AuthenticationError, BufferTooShort from multiprocessing.util import ( get_temp_dir, Finalize, sub_debug, debug, _eintr_retry) +from multiprocessing.forking import ForkingPickler try: import _winapi from _winapi import WAIT_OBJECT_0, WAIT_TIMEOUT, INFINITE @@ -227,8 +228,9 @@ """Send a (picklable) object""" self._check_closed() self._check_writable() - buf = pickle.dumps(obj, protocol=pickle.HIGHEST_PROTOCOL) - self._send_bytes(memoryview(buf)) + buf = io.BytesIO() + ForkingPickler(buf, pickle.HIGHEST_PROTOCOL).dump(obj) + self._send_bytes(buf.getbuffer()) def recv_bytes(self, maxlength=None): """ @@ -880,3 +882,21 @@ raise if timeout is not None: timeout = deadline - time.time() + +# +# Make connection and socket objects sharable if possible +# + +if sys.platform == 'win32': + from . import reduction + ForkingPickler.register(socket.socket, reduction.reduce_socket) + ForkingPickler.register(Connection, reduction.reduce_connection) + ForkingPickler.register(PipeConnection, reduction.reduce_pipe_connection) +else: + try: + from . import reduction + except ImportError: + pass + else: + ForkingPickler.register(socket.socket, reduction.reduce_socket) + ForkingPickler.register(Connection, reduction.reduce_connection) diff --git a/Lib/multiprocessing/forking.py b/Lib/multiprocessing/forking.py --- a/Lib/multiprocessing/forking.py +++ b/Lib/multiprocessing/forking.py @@ -407,25 +407,6 @@ return d - # - # Make (Pipe)Connection picklable - # - - # Late import because of circular import - from .connection import Connection, PipeConnection - - def reduce_connection(conn): - if not Popen.thread_is_spawning(): - raise RuntimeError( - 'By default %s objects can only be shared between processes\n' - 'using inheritance' % type(conn).__name__ - ) - return type(conn), (Popen.duplicate_for_child(conn.fileno()), - conn.readable, conn.writable) - - ForkingPickler.register(Connection, reduce_connection) - ForkingPickler.register(PipeConnection, reduce_connection) - # # Prepare current process # diff --git a/Lib/multiprocessing/reduction.py b/Lib/multiprocessing/reduction.py --- a/Lib/multiprocessing/reduction.py +++ b/Lib/multiprocessing/reduction.py @@ -33,7 +33,7 @@ # SUCH DAMAGE. # -__all__ = [] +__all__ = ['reduce_socket', 'reduce_connection', 'send_handle', 'recv_handle'] import os import sys @@ -42,9 +42,8 @@ import struct from multiprocessing import current_process -from multiprocessing.forking import Popen, duplicate, close, ForkingPickler from multiprocessing.util import register_after_fork, debug, sub_debug -from multiprocessing.connection import Client, Listener, Connection +from multiprocessing.util import is_exiting, sub_warning # @@ -60,22 +59,91 @@ # if sys.platform == 'win32': + # Windows + __all__ += ['reduce_pipe_connection'] import _winapi def send_handle(conn, handle, destination_pid): - process_handle = _winapi.OpenProcess( - _winapi.PROCESS_ALL_ACCESS, False, destination_pid - ) - try: - new_handle = duplicate(handle, process_handle) - conn.send(new_handle) - finally: - close(process_handle) + dh = DupHandle(handle, _winapi.DUPLICATE_SAME_ACCESS, destination_pid) + conn.send(dh) def recv_handle(conn): - return conn.recv() + return conn.recv().detach() + + class DupHandle(object): + def __init__(self, handle, access, pid=None): + # duplicate handle for process with given pid + if pid is None: + pid = os.getpid() + proc = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False, pid) + try: + self._handle = _winapi.DuplicateHandle( + _winapi.GetCurrentProcess(), + handle, proc, access, False, 0) + finally: + _winapi.CloseHandle(proc) + self._access = access + self._pid = pid + + def detach(self): + # retrieve handle from process which currently owns it + if self._pid == os.getpid(): + return self._handle + proc = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False, + self._pid) + try: + return _winapi.DuplicateHandle( + proc, self._handle, _winapi.GetCurrentProcess(), + self._access, False, _winapi.DUPLICATE_CLOSE_SOURCE) + finally: + _winapi.CloseHandle(proc) + + class DupSocket(object): + def __init__(self, sock): + new_sock = sock.dup() + def send(conn, pid): + share = new_sock.share(pid) + conn.send_bytes(share) + self._id = resource_sharer.register(send, new_sock.close) + + def detach(self): + conn = resource_sharer.get_connection(self._id) + try: + share = conn.recv_bytes() + return socket.fromshare(share) + finally: + conn.close() + + def reduce_socket(s): + return rebuild_socket, (DupSocket(s),) + + def rebuild_socket(ds): + return ds.detach() + + def reduce_connection(conn): + handle = conn.fileno() + with socket.fromfd(handle, socket.AF_INET, socket.SOCK_STREAM) as s: + ds = DupSocket(s) + return rebuild_connection, (ds, conn.readable, conn.writable) + + def rebuild_connection(ds, readable, writable): + from .connection import Connection + sock = ds.detach() + return Connection(sock.detach(), readable, writable) + + def reduce_pipe_connection(conn): + access = ((_winapi.FILE_GENERIC_READ if conn.readable else 0) | + (_winapi.FILE_GENERIC_WRITE if conn.writable else 0)) + dh = DupHandle(conn.fileno(), access) + return rebuild_pipe_connection, (dh, conn.readable, conn.writable) + + def rebuild_pipe_connection(dh, readable, writable): + from .connection import PipeConnection + handle = dh.detach() + return PipeConnection(handle, readable, writable) else: + # Unix def send_handle(conn, handle, destination_pid): with socket.fromfd(conn.fileno(), socket.AF_UNIX, socket.SOCK_STREAM) as s: s.sendmsg([b'x'], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, @@ -94,136 +162,109 @@ pass raise RuntimeError('Invalid data received') + class DupFd(object): + def __init__(self, fd): + new_fd = os.dup(fd) + def send(conn, pid): + send_handle(conn, new_fd, pid) + def close(): + os.close(new_fd) + self._id = resource_sharer.register(send, close) + + def detach(self): + conn = resource_sharer.get_connection(self._id) + try: + return recv_handle(conn) + finally: + conn.close() + + def reduce_socket(s): + df = DupFd(s.fileno()) + return rebuild_socket, (df, s.family, s.type, s.proto) + + def rebuild_socket(df, family, type, proto): + fd = df.detach() + s = socket.fromfd(fd, family, type, proto) + os.close(fd) + return s + + def reduce_connection(conn): + df = DupFd(conn.fileno()) + return rebuild_connection, (df, conn.readable, conn.writable) + + def rebuild_connection(df, readable, writable): + from .connection import Connection + fd = df.detach() + return Connection(fd, readable, writable) # -# Support for a per-process server thread which caches pickled handles +# Server which shares registered resources with clients # -_cache = set() +class ResourceSharer(object): + def __init__(self): + self._key = 0 + self._cache = {} + self._old_locks = [] + self._lock = threading.Lock() + self._listener = None + self._address = None + register_after_fork(self, ResourceSharer._afterfork) -def _reset(obj): - global _lock, _listener, _cache - for h in _cache: - close(h) - _cache.clear() - _lock = threading.Lock() - _listener = None + def register(self, send, close): + with self._lock: + if self._address is None: + self._start() + self._key += 1 + self._cache[self._key] = (send, close) + return (self._address, self._key) -_reset(None) -register_after_fork(_reset, _reset) + @staticmethod + def get_connection(ident): + from .connection import Client + address, key = ident + c = Client(address, authkey=current_process().authkey) + c.send((key, os.getpid())) + return c -def _get_listener(): - global _listener + def _afterfork(self): + for key, (send, close) in self._cache.items(): + close() + self._cache.clear() + # If self._lock was locked at the time of the fork, it may be broken + # -- see issue 6721. Replace it without letting it be gc'ed. + self._old_locks.append(self._lock) + self._lock = threading.Lock() + if self._listener is not None: + self._listener.close() + self._listener = None + self._address = None - if _listener is None: - _lock.acquire() - try: - if _listener is None: - debug('starting listener and thread for sending handles') - _listener = Listener(authkey=current_process().authkey) - t = threading.Thread(target=_serve) - t.daemon = True - t.start() - finally: - _lock.release() + def _start(self): + from .connection import Listener + assert self._listener is None + debug('starting listener and thread for sending handles') + self._listener = Listener(authkey=current_process().authkey) + self._address = self._listener.address + t = threading.Thread(target=self._serve) + t.daemon = True + t.start() - return _listener + def _serve(self): + while 1: + try: + conn = self._listener.accept() + key, destination_pid = conn.recv() + send, close = self._cache.pop(key) + send(conn, destination_pid) + close() + conn.close() + except: + if not is_exiting(): + import traceback + sub_warning( + 'thread for sharing handles raised exception :\n' + + '-'*79 + '\n' + traceback.format_exc() + '-'*79 + ) -def _serve(): - from .util import is_exiting, sub_warning - - while 1: - try: - conn = _listener.accept() - handle_wanted, destination_pid = conn.recv() - _cache.remove(handle_wanted) - send_handle(conn, handle_wanted, destination_pid) - close(handle_wanted) - conn.close() - except: - if not is_exiting(): - import traceback - sub_warning( - 'thread for sharing handles raised exception :\n' + - '-'*79 + '\n' + traceback.format_exc() + '-'*79 - ) - -# -# Functions to be used for pickling/unpickling objects with handles -# - -def reduce_handle(handle): - if Popen.thread_is_spawning(): - return (None, Popen.duplicate_for_child(handle), True) - dup_handle = duplicate(handle) - _cache.add(dup_handle) - sub_debug('reducing handle %d', handle) - return (_get_listener().address, dup_handle, False) - -def rebuild_handle(pickled_data): - address, handle, inherited = pickled_data - if inherited: - return handle - sub_debug('rebuilding handle %d', handle) - conn = Client(address, authkey=current_process().authkey) - conn.send((handle, os.getpid())) - new_handle = recv_handle(conn) - conn.close() - return new_handle - -# -# Register `Connection` with `ForkingPickler` -# - -def reduce_connection(conn): - rh = reduce_handle(conn.fileno()) - return rebuild_connection, (rh, conn.readable, conn.writable) - -def rebuild_connection(reduced_handle, readable, writable): - handle = rebuild_handle(reduced_handle) - return Connection( - handle, readable=readable, writable=writable - ) - -ForkingPickler.register(Connection, reduce_connection) - -# -# Register `socket.socket` with `ForkingPickler` -# - -def fromfd(fd, family, type_, proto=0): - s = socket.fromfd(fd, family, type_, proto) - if s.__class__ is not socket.socket: - s = socket.socket(_sock=s) - return s - -def reduce_socket(s): - reduced_handle = reduce_handle(s.fileno()) - return rebuild_socket, (reduced_handle, s.family, s.type, s.proto) - -def rebuild_socket(reduced_handle, family, type_, proto): - fd = rebuild_handle(reduced_handle) - _sock = fromfd(fd, family, type_, proto) - close(fd) - return _sock - -ForkingPickler.register(socket.socket, reduce_socket) - -# -# Register `_multiprocessing.PipeConnection` with `ForkingPickler` -# - -if sys.platform == 'win32': - from multiprocessing.connection import PipeConnection - - def reduce_pipe_connection(conn): - rh = reduce_handle(conn.fileno()) - return rebuild_pipe_connection, (rh, conn.readable, conn.writable) - - def rebuild_pipe_connection(reduced_handle, readable, writable): - handle = rebuild_handle(reduced_handle) - return PipeConnection( - handle, readable=readable, writable=writable - ) - - ForkingPickler.register(PipeConnection, reduce_pipe_connection) +resource_sharer = ResourceSharer() diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -1959,49 +1959,49 @@ # # Test of sending connection and socket objects between processes # -""" + + at unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction") class _TestPicklingConnections(BaseTestCase): ALLOWED_TYPES = ('processes',) - def _listener(self, conn, families): + @classmethod + def _listener(cls, conn, families): for fam in families: - l = self.connection.Listener(family=fam) + l = cls.connection.Listener(family=fam) conn.send(l.address) new_conn = l.accept() conn.send(new_conn) - - if self.TYPE == 'processes': - l = socket.socket() - l.bind(('localhost', 0)) - conn.send(l.getsockname()) - l.listen(1) - new_conn, addr = l.accept() - conn.send(new_conn) + new_conn.close() + l.close() + + l = socket.socket() + l.bind(('localhost', 0)) + conn.send(l.getsockname()) + l.listen(1) + new_conn, addr = l.accept() + conn.send(new_conn) + new_conn.close() + l.close() conn.recv() - def _remote(self, conn): + @classmethod + def _remote(cls, conn): for (address, msg) in iter(conn.recv, None): - client = self.connection.Client(address) + client = cls.connection.Client(address) client.send(msg.upper()) client.close() - if self.TYPE == 'processes': - address, msg = conn.recv() - client = socket.socket() - client.connect(address) - client.sendall(msg.upper()) - client.close() + address, msg = conn.recv() + client = socket.socket() + client.connect(address) + client.sendall(msg.upper()) + client.close() conn.close() def test_pickling(self): - try: - multiprocessing.allow_connection_pickling() - except ImportError: - return - families = self.connection.families lconn, lconn0 = self.Pipe() @@ -2025,16 +2025,12 @@ rconn.send(None) - if self.TYPE == 'processes': - msg = latin('This connection uses a normal socket') - address = lconn.recv() - rconn.send((address, msg)) - if hasattr(socket, 'fromfd'): - new_conn = lconn.recv() - self.assertEqual(new_conn.recv(100), msg.upper()) - else: - # XXX On Windows with Py2.6 need to backport fromfd() - discard = lconn.recv_bytes() + msg = latin('This connection uses a normal socket') + address = lconn.recv() + rconn.send((address, msg)) + new_conn = lconn.recv() + self.assertEqual(new_conn.recv(100), msg.upper()) + new_conn.close() lconn.send(None) @@ -2043,7 +2039,46 @@ lp.join() rp.join() -""" + + @classmethod + def child_access(cls, conn): + w = conn.recv() + w.send('all is well') + w.close() + + r = conn.recv() + msg = r.recv() + conn.send(msg*2) + + conn.close() + + def test_access(self): + # On Windows, if we do not specify a destination pid when + # using DupHandle then we need to be careful to use the + # correct access flags for DuplicateHandle(), or else + # DupHandle.detach() will raise PermissionError. For example, + # for a read only pipe handle we should use + # access=FILE_GENERIC_READ. (Unfortunately + # DUPLICATE_SAME_ACCESS does not work.) + conn, child_conn = self.Pipe() + p = self.Process(target=self.child_access, args=(child_conn,)) + p.daemon = True + p.start() + child_conn.close() + + r, w = self.Pipe(duplex=False) + conn.send(w) + w.close() + self.assertEqual(r.recv(), 'all is well') + r.close() + + r, w = self.Pipe(duplex=False) + conn.send(r) + r.close() + w.send('foobar') + w.close() + self.assertEqual(conn.recv(), 'foobar'*2) + # # # diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -71,6 +71,9 @@ Library ------- +- Issue #4892: multiprocessing Connections can now be transferred over + multiprocessing Connections. Patch by Richard Oudkerk (sbt). + - Issue #14160: TarFile.extractfile() failed to resolve symbolic links when the links were not located in an archive subdirectory. diff --git a/Modules/_winapi.c b/Modules/_winapi.c --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -1280,6 +1280,7 @@ WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE); WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP); WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS); + WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE); WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS); WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE); WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); @@ -1298,6 +1299,8 @@ WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT); WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE); WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED); + WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ); + WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE); WINAPI_CONSTANT(F_DWORD, GENERIC_READ); WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE); WINAPI_CONSTANT(F_DWORD, INFINITE); @@ -1310,6 +1313,7 @@ WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES); WINAPI_CONSTANT(F_DWORD, PIPE_WAIT); WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS); + WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE); WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW); WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES); WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 00:33:44 2012 From: python-checkins at python.org (vinay.sajip) Date: Wed, 25 Apr 2012 00:33:44 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NjMy?= =?utf8?q?=3A_Updated_WatchedFileHandler_to_deal_with_race_condition=2E_Th?= =?utf8?q?anks_to?= Message-ID: http://hg.python.org/cpython/rev/15a33d7d2b50 changeset: 76542:15a33d7d2b50 branch: 2.7 parent: 76540:aff14bea5596 user: Vinay Sajip date: Tue Apr 24 23:15:10 2012 +0100 summary: Issue #14632: Updated WatchedFileHandler to deal with race condition. Thanks to John Mulligan for the problem report and patch. files: Lib/logging/handlers.py | 48 ++++++++++++++++----------- Lib/test/test_logging.py | 41 +++++++++++++++++++++++- 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -23,7 +23,7 @@ To use, simply 'import logging.handlers' and log away! """ -import logging, socket, os, cPickle, struct, time, re +import errno, logging, socket, os, cPickle, struct, time, re from stat import ST_DEV, ST_INO, ST_MTIME try: @@ -392,11 +392,13 @@ """ def __init__(self, filename, mode='a', encoding=None, delay=0): logging.FileHandler.__init__(self, filename, mode, encoding, delay) - if not os.path.exists(self.baseFilename): - self.dev, self.ino = -1, -1 - else: - stat = os.stat(self.baseFilename) - self.dev, self.ino = stat[ST_DEV], stat[ST_INO] + self.dev, self.ino = -1, -1 + self._statstream() + + def _statstream(self): + if self.stream: + sres = os.fstat(self.stream.fileno()) + self.dev, self.ino = sres[ST_DEV], sres[ST_INO] def emit(self, record): """ @@ -406,19 +408,27 @@ has, close the old stream and reopen the file to get the current stream. """ - if not os.path.exists(self.baseFilename): - stat = None - changed = 1 - else: - stat = os.stat(self.baseFilename) - changed = (stat[ST_DEV] != self.dev) or (stat[ST_INO] != self.ino) - if changed and self.stream is not None: - self.stream.flush() - self.stream.close() - self.stream = self._open() - if stat is None: - stat = os.stat(self.baseFilename) - self.dev, self.ino = stat[ST_DEV], stat[ST_INO] + # Reduce the chance of race conditions by stat'ing by path only + # once and then fstat'ing our new fd if we opened a new log stream. + # See issue #14632: Thanks to John Mulligan for the problem report + # and patch. + try: + # stat the file by path, checking for existence + sres = os.stat(self.baseFilename) + except OSError as err: + if err.errno == errno.ENOENT: + sres = None + else: + raise + # compare file system stat with that of our stream file handle + if not sres or sres[ST_DEV] != self.dev or sres[ST_INO] != self.ino: + if self.stream is not None: + # we have an open file handle, clean it up + self.stream.flush() + self.stream.close() + # open a new file handle and get new stat info from that fd + self.stream = self._open() + self._statstream() logging.FileHandler.emit(self, record) class SocketHandler(logging.Handler): diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -31,6 +31,7 @@ import gc import json import os +import random import re import select import socket @@ -40,6 +41,7 @@ import tempfile from test.test_support import captured_stdout, run_with_locale, run_unittest import textwrap +import time import unittest import warnings import weakref @@ -1873,6 +1875,43 @@ self.assertTrue(c2 is c3) +class HandlerTest(BaseTest): + + @unittest.skipUnless(threading, 'Threading required for this test.') + def test_race(self): + # Issue #14632 refers. + def remove_loop(fname, tries): + for _ in range(tries): + try: + os.unlink(fname) + except OSError: + pass + time.sleep(0.004 * random.randint(0, 4)) + + def cleanup(remover, fn, handler): + handler.close() + remover.join() + if os.path.exists(fn): + os.unlink(fn) + + fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') + os.close(fd) + del_count = 1000 + log_count = 1000 + remover = threading.Thread(target=remove_loop, args=(fn, del_count)) + remover.daemon = True + remover.start() + for delay in (False, True): + h = logging.handlers.WatchedFileHandler(fn, delay=delay) + self.addCleanup(cleanup, remover, fn, h) + f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') + h.setFormatter(f) + for _ in range(log_count): + time.sleep(0.005) + r = logging.makeLogRecord({'msg': 'testing' }) + h.handle(r) + + # Set the locale to the platform-dependent default. I have no idea # why the test does this, but in any case we save the current locale # first and restore it at the end. @@ -1882,7 +1921,7 @@ CustomLevelsAndFiltersTest, MemoryHandlerTest, ConfigFileTest, SocketHandlerTest, MemoryTest, EncodingTest, WarningsTest, ConfigDictTest, ManagerTest, - ChildLoggerTest) + ChildLoggerTest, HandlerTest) if __name__ == "__main__": test_main() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 00:33:45 2012 From: python-checkins at python.org (vinay.sajip) Date: Wed, 25 Apr 2012 00:33:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Updated_year_in?= =?utf8?q?_docstring/comment=2E?= Message-ID: http://hg.python.org/cpython/rev/9cfe6845b1df changeset: 76543:9cfe6845b1df branch: 2.7 user: Vinay Sajip date: Tue Apr 24 23:17:29 2012 +0100 summary: Updated year in docstring/comment. files: Lib/test/test_logging.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2001-2010 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -18,7 +18,7 @@ """Test harness for the logging module. Run all tests. -Copyright (C) 2001-2010 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved. """ import logging -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 00:33:45 2012 From: python-checkins at python.org (vinay.sajip) Date: Wed, 25 Apr 2012 00:33:45 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NjMy?= =?utf8?q?=3A_Updated_WatchedFileHandler_to_deal_with_race_condition=2E_Th?= =?utf8?q?anks_to?= Message-ID: http://hg.python.org/cpython/rev/5de7c3d64f2a changeset: 76544:5de7c3d64f2a branch: 3.2 parent: 76538:0adf4fd8df83 user: Vinay Sajip date: Tue Apr 24 23:25:30 2012 +0100 summary: Issue #14632: Updated WatchedFileHandler to deal with race condition. Thanks to John Mulligan for the problem report and patch. files: Lib/logging/handlers.py | 49 +++++++++++++++++---------- Lib/test/test_logging.py | 46 ++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -23,7 +23,7 @@ To use, simply 'import logging.handlers' and log away! """ -import logging, socket, os, pickle, struct, time, re +import errno, logging, socket, os, pickle, struct, time, re from stat import ST_DEV, ST_INO, ST_MTIME import queue try: @@ -383,11 +383,13 @@ """ def __init__(self, filename, mode='a', encoding=None, delay=0): logging.FileHandler.__init__(self, filename, mode, encoding, delay) - if not os.path.exists(self.baseFilename): - self.dev, self.ino = -1, -1 - else: - stat = os.stat(self.baseFilename) - self.dev, self.ino = stat[ST_DEV], stat[ST_INO] + self.dev, self.ino = -1, -1 + self._statstream() + + def _statstream(self): + if self.stream: + sres = os.fstat(self.stream.fileno()) + self.dev, self.ino = sres[ST_DEV], sres[ST_INO] def emit(self, record): """ @@ -397,21 +399,30 @@ has, close the old stream and reopen the file to get the current stream. """ - if not os.path.exists(self.baseFilename): - stat = None - changed = 1 - else: - stat = os.stat(self.baseFilename) - changed = (stat[ST_DEV] != self.dev) or (stat[ST_INO] != self.ino) - if changed and self.stream is not None: - self.stream.flush() - self.stream.close() - self.stream = self._open() - if stat is None: - stat = os.stat(self.baseFilename) - self.dev, self.ino = stat[ST_DEV], stat[ST_INO] + # Reduce the chance of race conditions by stat'ing by path only + # once and then fstat'ing our new fd if we opened a new log stream. + # See issue #14632: Thanks to John Mulligan for the problem report + # and patch. + try: + # stat the file by path, checking for existence + sres = os.stat(self.baseFilename) + except OSError as err: + if err.errno == errno.ENOENT: + sres = None + else: + raise + # compare file system stat with that of our stream file handle + if not sres or sres[ST_DEV] != self.dev or sres[ST_INO] != self.ino: + if self.stream is not None: + # we have an open file handle, clean it up + self.stream.flush() + self.stream.close() + # open a new file handle and get new stat info from that fd + self.stream = self._open() + self._statstream() logging.FileHandler.emit(self, record) + class SocketHandler(logging.Handler): """ A handler class which writes logging records, in pickle format, to diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2001-2011 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -18,7 +18,7 @@ """Test harness for the logging module. Run all tests. -Copyright (C) 2001-2011 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved. """ import logging @@ -33,6 +33,7 @@ import json import os import queue +import random import re import select import socket @@ -43,6 +44,7 @@ from test.support import captured_stdout, run_with_locale, run_unittest from test.support import TestHandler, Matcher import textwrap +import time import unittest import warnings import weakref @@ -2301,7 +2303,6 @@ # Failures occur on some systems for MIDNIGHT and W0. # Print detailed calculation for MIDNIGHT so we can try to see # what's going on - import time if when == 'MIDNIGHT': try: if rh.utc: @@ -2328,6 +2329,43 @@ rh.close() setattr(TimedRotatingFileHandlerTest, "test_compute_rollover_%s" % when, test_compute_rollover) +class HandlerTest(BaseTest): + + @unittest.skipUnless(threading, 'Threading required for this test.') + def test_race(self): + # Issue #14632 refers. + def remove_loop(fname, tries): + for _ in range(tries): + try: + os.unlink(fname) + except OSError: + pass + time.sleep(0.004 * random.randint(0, 4)) + + def cleanup(remover, fn, handler): + handler.close() + remover.join() + if os.path.exists(fn): + os.unlink(fn) + + fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') + os.close(fd) + del_count = 1000 + log_count = 1000 + remover = threading.Thread(target=remove_loop, args=(fn, del_count)) + remover.daemon = True + remover.start() + for delay in (False, True): + h = logging.handlers.WatchedFileHandler(fn, delay=delay) + self.addCleanup(cleanup, remover, fn, h) + f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') + h.setFormatter(f) + for _ in range(log_count): + time.sleep(0.005) + r = logging.makeLogRecord({'msg': 'testing' }) + h.handle(r) + + # Set the locale to the platform-dependent default. I have no idea # why the test does this, but in any case we save the current locale # first and restore it at the end. @@ -2341,7 +2379,7 @@ LogRecordFactoryTest, ChildLoggerTest, QueueHandlerTest, RotatingFileHandlerTest, LastResortTest, - TimedRotatingFileHandlerTest + TimedRotatingFileHandlerTest, HandlerTest, ) if __name__ == "__main__": -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 00:33:46 2012 From: python-checkins at python.org (vinay.sajip) Date: Wed, 25 Apr 2012 00:33:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314632=3A_Updated_WatchedFileHandler_to_deal_with_ra?= =?utf8?q?ce_condition=2E_Thanks_to?= Message-ID: http://hg.python.org/cpython/rev/380821b47872 changeset: 76545:380821b47872 parent: 76541:08d4c2fe51ea parent: 76544:5de7c3d64f2a user: Vinay Sajip date: Tue Apr 24 23:33:33 2012 +0100 summary: Issue #14632: Updated WatchedFileHandler to deal with race condition. Thanks to John Mulligan for the problem report and patch. files: Lib/logging/handlers.py | 49 +++++++++++++++++---------- Lib/test/test_logging.py | 45 ++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -23,7 +23,7 @@ To use, simply 'import logging.handlers' and log away! """ -import logging, socket, os, pickle, struct, time, re +import errno, logging, socket, os, pickle, struct, time, re from codecs import BOM_UTF8 from stat import ST_DEV, ST_INO, ST_MTIME import queue @@ -419,11 +419,13 @@ """ def __init__(self, filename, mode='a', encoding=None, delay=False): logging.FileHandler.__init__(self, filename, mode, encoding, delay) - if not os.path.exists(self.baseFilename): - self.dev, self.ino = -1, -1 - else: - stat = os.stat(self.baseFilename) - self.dev, self.ino = stat[ST_DEV], stat[ST_INO] + self.dev, self.ino = -1, -1 + self._statstream() + + def _statstream(self): + if self.stream: + sres = os.fstat(self.stream.fileno()) + self.dev, self.ino = sres[ST_DEV], sres[ST_INO] def emit(self, record): """ @@ -433,21 +435,30 @@ has, close the old stream and reopen the file to get the current stream. """ - if not os.path.exists(self.baseFilename): - stat = None - changed = True - else: - stat = os.stat(self.baseFilename) - changed = (stat[ST_DEV] != self.dev) or (stat[ST_INO] != self.ino) - if changed and self.stream is not None: - self.stream.flush() - self.stream.close() - self.stream = self._open() - if stat is None: - stat = os.stat(self.baseFilename) - self.dev, self.ino = stat[ST_DEV], stat[ST_INO] + # Reduce the chance of race conditions by stat'ing by path only + # once and then fstat'ing our new fd if we opened a new log stream. + # See issue #14632: Thanks to John Mulligan for the problem report + # and patch. + try: + # stat the file by path, checking for existence + sres = os.stat(self.baseFilename) + except OSError as err: + if err.errno == errno.ENOENT: + sres = None + else: + raise + # compare file system stat with that of our stream file handle + if not sres or sres[ST_DEV] != self.dev or sres[ST_INO] != self.ino: + if self.stream is not None: + # we have an open file handle, clean it up + self.stream.flush() + self.stream.close() + # open a new file handle and get new stat info from that fd + self.stream = self._open() + self._statstream() logging.FileHandler.emit(self, record) + class SocketHandler(logging.Handler): """ A handler class which writes logging records, in pickle format, to diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2001-2011 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -18,7 +18,7 @@ """Test harness for the logging module. Run all tests. -Copyright (C) 2001-2011 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved. """ import logging @@ -33,6 +33,7 @@ import json import os import queue +import random import re import select import socket @@ -539,8 +540,8 @@ h = logging.handlers.WatchedFileHandler(fn, delay=True) if existing: dev, ino = h.dev, h.ino - self.assertNotEqual(dev, -1) - self.assertNotEqual(ino, -1) + self.assertEqual(dev, -1) + self.assertEqual(ino, -1) r = logging.makeLogRecord({'msg': 'Test'}) h.handle(r) # Now remove the file. @@ -581,6 +582,41 @@ self.assertFalse(h.shouldFlush(r)) h.close() + @unittest.skipUnless(threading, 'Threading required for this test.') + def test_race(self): + # Issue #14632 refers. + def remove_loop(fname, tries): + for _ in range(tries): + try: + os.unlink(fname) + except OSError: + pass + time.sleep(0.004 * random.randint(0, 4)) + + def cleanup(remover, fn, handler): + handler.close() + remover.join() + if os.path.exists(fn): + os.unlink(fn) + + fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') + os.close(fd) + del_count = 1000 + log_count = 1000 + remover = threading.Thread(target=remove_loop, args=(fn, del_count)) + remover.daemon = True + remover.start() + for delay in (False, True): + h = logging.handlers.WatchedFileHandler(fn, delay=delay) + self.addCleanup(cleanup, remover, fn, h) + f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') + h.setFormatter(f) + for _ in range(log_count): + time.sleep(0.005) + r = logging.makeLogRecord({'msg': 'testing' }) + h.handle(r) + + class BadStream(object): def write(self, data): raise RuntimeError('deliberate mistake') @@ -3724,7 +3760,6 @@ # Failures occur on some systems for MIDNIGHT and W0. # Print detailed calculation for MIDNIGHT so we can try to see # what's going on - import time if when == 'MIDNIGHT': try: if rh.utc: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 01:37:03 2012 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 25 Apr 2012 01:37:03 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Rename_?= =?utf8?q?=5FSourcelessFileLoader_to_SourcelessFileLoader?= Message-ID: http://hg.python.org/cpython/rev/8aa4737d67d2 changeset: 76546:8aa4737d67d2 user: Marc-Andre Lemburg date: Wed Apr 25 01:36:48 2012 +0200 summary: Issue #14605: Rename _SourcelessFileLoader to SourcelessFileLoader files: Doc/library/importlib.rst | 13 +++------ Lib/imp.py | 2 +- Lib/importlib/_bootstrap.py | 4 +- Lib/importlib/abc.py | 2 +- Lib/importlib/machinery.py | 2 +- Lib/importlib/test/source/test_case_sensitivity.py | 2 +- Lib/importlib/test/source/test_file_loader.py | 2 +- Lib/importlib/test/source/test_finder.py | 2 +- Lib/importlib/test/test_abc.py | 2 +- Misc/NEWS | 2 +- 10 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -606,18 +606,15 @@ Load the specified module if it is the same as :attr:`name`. -.. class:: _SourcelessFileLoader(fullname, path) +.. class:: SourcelessFileLoader(fullname, path) A concrete implementation of :class:`importlib.abc.FileLoader` which can import bytecode files (i.e. no source code files exist). - It is **strongly** suggested you do not rely on this loader (hence the - leading underscore of the class). Direct use of bytecode files (and thus not - source code files) inhibits your modules from being usable by all Python - implementations. It also runs the risk of your bytecode files not being - usable by new versions of Python which change the bytecode format. This - class is only documented as it is directly used by import and thus can - potentially have instances show up as a module's ``__loader__`` attribute. + Please note that direct use of bytecode files (and thus not source code + files) inhibits your modules from being usable by all Python + implementations or new versions of Python which change the bytecode + format. .. versionadded:: 3.3 diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -94,7 +94,7 @@ class _LoadCompiledCompatibility(_HackedGetData, - _bootstrap._SourcelessFileLoader): + _bootstrap.SourcelessFileLoader): """Compatibility support for implementing load_compiled().""" diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -671,7 +671,7 @@ pass -class _SourcelessFileLoader(FileLoader, _LoaderBasics): +class SourcelessFileLoader(FileLoader, _LoaderBasics): """Loader which handles sourceless file imports.""" @@ -1198,7 +1198,7 @@ supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), (SourceFileLoader, _suffix_list(1), True), - (_SourcelessFileLoader, _suffix_list(2), True)] + (SourcelessFileLoader, _suffix_list(2), True)] setattr(self_module, '_DEFAULT_PATH_HOOK', FileFinder.path_hook(*supported_loaders)) diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -119,7 +119,7 @@ ExecutionLoader ABCs.""" _register(FileLoader, machinery.SourceFileLoader, - machinery._SourcelessFileLoader) + machinery.SourcelessFileLoader) class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader): diff --git a/Lib/importlib/machinery.py b/Lib/importlib/machinery.py --- a/Lib/importlib/machinery.py +++ b/Lib/importlib/machinery.py @@ -5,5 +5,5 @@ from ._bootstrap import PathFinder from ._bootstrap import FileFinder from ._bootstrap import SourceFileLoader -from ._bootstrap import _SourcelessFileLoader +from ._bootstrap import SourcelessFileLoader from ._bootstrap import ExtensionFileLoader diff --git a/Lib/importlib/test/source/test_case_sensitivity.py b/Lib/importlib/test/source/test_case_sensitivity.py --- a/Lib/importlib/test/source/test_case_sensitivity.py +++ b/Lib/importlib/test/source/test_case_sensitivity.py @@ -24,7 +24,7 @@ (_bootstrap.SourceFileLoader, _bootstrap._suffix_list(imp.PY_SOURCE), True), - (_bootstrap._SourcelessFileLoader, + (_bootstrap.SourcelessFileLoader, _bootstrap._suffix_list(imp.PY_COMPILED), True)) return finder.find_module(self.name) diff --git a/Lib/importlib/test/source/test_file_loader.py b/Lib/importlib/test/source/test_file_loader.py --- a/Lib/importlib/test/source/test_file_loader.py +++ b/Lib/importlib/test/source/test_file_loader.py @@ -379,7 +379,7 @@ class SourcelessLoaderBadBytecodeTest(BadBytecodeTest): - loader = _bootstrap._SourcelessFileLoader + loader = _bootstrap.SourcelessFileLoader def test_empty_file(self): def test(name, mapping, bytecode_path): diff --git a/Lib/importlib/test/source/test_finder.py b/Lib/importlib/test/source/test_finder.py --- a/Lib/importlib/test/source/test_finder.py +++ b/Lib/importlib/test/source/test_finder.py @@ -38,7 +38,7 @@ def import_(self, root, module): loader_details = [(_bootstrap.SourceFileLoader, _bootstrap._suffix_list(imp.PY_SOURCE), True), - (_bootstrap._SourcelessFileLoader, + (_bootstrap.SourcelessFileLoader, _bootstrap._suffix_list(imp.PY_COMPILED), True)] finder = _bootstrap.FileFinder(root, *loader_details) return finder.find_module(module) diff --git a/Lib/importlib/test/test_abc.py b/Lib/importlib/test/test_abc.py --- a/Lib/importlib/test/test_abc.py +++ b/Lib/importlib/test/test_abc.py @@ -62,7 +62,7 @@ class FileLoader(InheritanceTests, unittest.TestCase): superclasses = [abc.ResourceLoader, abc.ExecutionLoader] - subclasses = [machinery.SourceFileLoader, machinery._SourcelessFileLoader] + subclasses = [machinery.SourceFileLoader, machinery.SourcelessFileLoader] class SourceLoader(InheritanceTests, unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,7 +84,7 @@ which send EOF without trailing \r\n. - Issue #14605: Add importlib.abc.FileLoader, importlib.machinery.(FileFinder, - SourceFileLoader, _SourcelessFileLoader, ExtensionFileLoader). + SourceFileLoader, SourcelessFileLoader, ExtensionFileLoader). - Issue #13959: imp.cache_from_source()/source_from_cache() now follow os.path.join()/split() semantics for path manipulation instead of its prior, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 02:11:17 2012 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 25 Apr 2012 02:11:17 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Revert_re?= =?utf8?q?naming_of_=5FSourcelessFileLoader=2C_since_it_caused?= Message-ID: http://hg.python.org/cpython/rev/e30196bfc11d changeset: 76547:e30196bfc11d user: Marc-Andre Lemburg date: Wed Apr 25 02:11:07 2012 +0200 summary: Issue #14605: Revert renaming of _SourcelessFileLoader, since it caused the buildbots to fail. files: Doc/library/importlib.rst | 13 ++++++--- Lib/imp.py | 2 +- Lib/importlib/_bootstrap.py | 4 +- Lib/importlib/abc.py | 2 +- Lib/importlib/machinery.py | 2 +- Lib/importlib/test/source/test_case_sensitivity.py | 2 +- Lib/importlib/test/source/test_file_loader.py | 2 +- Lib/importlib/test/source/test_finder.py | 2 +- Lib/importlib/test/test_abc.py | 2 +- Misc/NEWS | 2 +- 10 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -606,15 +606,18 @@ Load the specified module if it is the same as :attr:`name`. -.. class:: SourcelessFileLoader(fullname, path) +.. class:: _SourcelessFileLoader(fullname, path) A concrete implementation of :class:`importlib.abc.FileLoader` which can import bytecode files (i.e. no source code files exist). - Please note that direct use of bytecode files (and thus not source code - files) inhibits your modules from being usable by all Python - implementations or new versions of Python which change the bytecode - format. + It is **strongly** suggested you do not rely on this loader (hence the + leading underscore of the class). Direct use of bytecode files (and thus not + source code files) inhibits your modules from being usable by all Python + implementations. It also runs the risk of your bytecode files not being + usable by new versions of Python which change the bytecode format. This + class is only documented as it is directly used by import and thus can + potentially have instances show up as a module's ``__loader__`` attribute. .. versionadded:: 3.3 diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -94,7 +94,7 @@ class _LoadCompiledCompatibility(_HackedGetData, - _bootstrap.SourcelessFileLoader): + _bootstrap._SourcelessFileLoader): """Compatibility support for implementing load_compiled().""" diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -671,7 +671,7 @@ pass -class SourcelessFileLoader(FileLoader, _LoaderBasics): +class _SourcelessFileLoader(FileLoader, _LoaderBasics): """Loader which handles sourceless file imports.""" @@ -1198,7 +1198,7 @@ supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), (SourceFileLoader, _suffix_list(1), True), - (SourcelessFileLoader, _suffix_list(2), True)] + (_SourcelessFileLoader, _suffix_list(2), True)] setattr(self_module, '_DEFAULT_PATH_HOOK', FileFinder.path_hook(*supported_loaders)) diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -119,7 +119,7 @@ ExecutionLoader ABCs.""" _register(FileLoader, machinery.SourceFileLoader, - machinery.SourcelessFileLoader) + machinery._SourcelessFileLoader) class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader): diff --git a/Lib/importlib/machinery.py b/Lib/importlib/machinery.py --- a/Lib/importlib/machinery.py +++ b/Lib/importlib/machinery.py @@ -5,5 +5,5 @@ from ._bootstrap import PathFinder from ._bootstrap import FileFinder from ._bootstrap import SourceFileLoader -from ._bootstrap import SourcelessFileLoader +from ._bootstrap import _SourcelessFileLoader from ._bootstrap import ExtensionFileLoader diff --git a/Lib/importlib/test/source/test_case_sensitivity.py b/Lib/importlib/test/source/test_case_sensitivity.py --- a/Lib/importlib/test/source/test_case_sensitivity.py +++ b/Lib/importlib/test/source/test_case_sensitivity.py @@ -24,7 +24,7 @@ (_bootstrap.SourceFileLoader, _bootstrap._suffix_list(imp.PY_SOURCE), True), - (_bootstrap.SourcelessFileLoader, + (_bootstrap._SourcelessFileLoader, _bootstrap._suffix_list(imp.PY_COMPILED), True)) return finder.find_module(self.name) diff --git a/Lib/importlib/test/source/test_file_loader.py b/Lib/importlib/test/source/test_file_loader.py --- a/Lib/importlib/test/source/test_file_loader.py +++ b/Lib/importlib/test/source/test_file_loader.py @@ -379,7 +379,7 @@ class SourcelessLoaderBadBytecodeTest(BadBytecodeTest): - loader = _bootstrap.SourcelessFileLoader + loader = _bootstrap._SourcelessFileLoader def test_empty_file(self): def test(name, mapping, bytecode_path): diff --git a/Lib/importlib/test/source/test_finder.py b/Lib/importlib/test/source/test_finder.py --- a/Lib/importlib/test/source/test_finder.py +++ b/Lib/importlib/test/source/test_finder.py @@ -38,7 +38,7 @@ def import_(self, root, module): loader_details = [(_bootstrap.SourceFileLoader, _bootstrap._suffix_list(imp.PY_SOURCE), True), - (_bootstrap.SourcelessFileLoader, + (_bootstrap._SourcelessFileLoader, _bootstrap._suffix_list(imp.PY_COMPILED), True)] finder = _bootstrap.FileFinder(root, *loader_details) return finder.find_module(module) diff --git a/Lib/importlib/test/test_abc.py b/Lib/importlib/test/test_abc.py --- a/Lib/importlib/test/test_abc.py +++ b/Lib/importlib/test/test_abc.py @@ -62,7 +62,7 @@ class FileLoader(InheritanceTests, unittest.TestCase): superclasses = [abc.ResourceLoader, abc.ExecutionLoader] - subclasses = [machinery.SourceFileLoader, machinery.SourcelessFileLoader] + subclasses = [machinery.SourceFileLoader, machinery._SourcelessFileLoader] class SourceLoader(InheritanceTests, unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,7 +84,7 @@ which send EOF without trailing \r\n. - Issue #14605: Add importlib.abc.FileLoader, importlib.machinery.(FileFinder, - SourceFileLoader, SourcelessFileLoader, ExtensionFileLoader). + SourceFileLoader, _SourcelessFileLoader, ExtensionFileLoader). - Issue #13959: imp.cache_from_source()/source_from_cache() now follow os.path.join()/split() semantics for path manipulation instead of its prior, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 02:32:25 2012 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 25 Apr 2012 02:32:25 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Rename_?= =?utf8?q?=5FSourcelessFileLoader_to_SourcelessFileLoader=2E?= Message-ID: http://hg.python.org/cpython/rev/a2cf07135e4f changeset: 76548:a2cf07135e4f user: Marc-Andre Lemburg date: Wed Apr 25 02:31:37 2012 +0200 summary: Issue #14605: Rename _SourcelessFileLoader to SourcelessFileLoader. This time also recreating the Python/importlib.h file to make make happy. See the ticket for details. files: Doc/library/importlib.rst | 13 +++------ Lib/imp.py | 2 +- Lib/importlib/_bootstrap.py | 4 +- Lib/importlib/abc.py | 2 +- Lib/importlib/machinery.py | 2 +- Lib/importlib/test/source/test_case_sensitivity.py | 2 +- Lib/importlib/test/source/test_file_loader.py | 2 +- Lib/importlib/test/source/test_finder.py | 2 +- Lib/importlib/test/test_abc.py | 2 +- Misc/NEWS | 2 +- Python/importlib.h | Bin 11 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -606,18 +606,15 @@ Load the specified module if it is the same as :attr:`name`. -.. class:: _SourcelessFileLoader(fullname, path) +.. class:: SourcelessFileLoader(fullname, path) A concrete implementation of :class:`importlib.abc.FileLoader` which can import bytecode files (i.e. no source code files exist). - It is **strongly** suggested you do not rely on this loader (hence the - leading underscore of the class). Direct use of bytecode files (and thus not - source code files) inhibits your modules from being usable by all Python - implementations. It also runs the risk of your bytecode files not being - usable by new versions of Python which change the bytecode format. This - class is only documented as it is directly used by import and thus can - potentially have instances show up as a module's ``__loader__`` attribute. + Please note that direct use of bytecode files (and thus not source code + files) inhibits your modules from being usable by all Python + implementations or new versions of Python which change the bytecode + format. .. versionadded:: 3.3 diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -94,7 +94,7 @@ class _LoadCompiledCompatibility(_HackedGetData, - _bootstrap._SourcelessFileLoader): + _bootstrap.SourcelessFileLoader): """Compatibility support for implementing load_compiled().""" diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -671,7 +671,7 @@ pass -class _SourcelessFileLoader(FileLoader, _LoaderBasics): +class SourcelessFileLoader(FileLoader, _LoaderBasics): """Loader which handles sourceless file imports.""" @@ -1198,7 +1198,7 @@ supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), (SourceFileLoader, _suffix_list(1), True), - (_SourcelessFileLoader, _suffix_list(2), True)] + (SourcelessFileLoader, _suffix_list(2), True)] setattr(self_module, '_DEFAULT_PATH_HOOK', FileFinder.path_hook(*supported_loaders)) diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -119,7 +119,7 @@ ExecutionLoader ABCs.""" _register(FileLoader, machinery.SourceFileLoader, - machinery._SourcelessFileLoader) + machinery.SourcelessFileLoader) class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader): diff --git a/Lib/importlib/machinery.py b/Lib/importlib/machinery.py --- a/Lib/importlib/machinery.py +++ b/Lib/importlib/machinery.py @@ -5,5 +5,5 @@ from ._bootstrap import PathFinder from ._bootstrap import FileFinder from ._bootstrap import SourceFileLoader -from ._bootstrap import _SourcelessFileLoader +from ._bootstrap import SourcelessFileLoader from ._bootstrap import ExtensionFileLoader diff --git a/Lib/importlib/test/source/test_case_sensitivity.py b/Lib/importlib/test/source/test_case_sensitivity.py --- a/Lib/importlib/test/source/test_case_sensitivity.py +++ b/Lib/importlib/test/source/test_case_sensitivity.py @@ -24,7 +24,7 @@ (_bootstrap.SourceFileLoader, _bootstrap._suffix_list(imp.PY_SOURCE), True), - (_bootstrap._SourcelessFileLoader, + (_bootstrap.SourcelessFileLoader, _bootstrap._suffix_list(imp.PY_COMPILED), True)) return finder.find_module(self.name) diff --git a/Lib/importlib/test/source/test_file_loader.py b/Lib/importlib/test/source/test_file_loader.py --- a/Lib/importlib/test/source/test_file_loader.py +++ b/Lib/importlib/test/source/test_file_loader.py @@ -379,7 +379,7 @@ class SourcelessLoaderBadBytecodeTest(BadBytecodeTest): - loader = _bootstrap._SourcelessFileLoader + loader = _bootstrap.SourcelessFileLoader def test_empty_file(self): def test(name, mapping, bytecode_path): diff --git a/Lib/importlib/test/source/test_finder.py b/Lib/importlib/test/source/test_finder.py --- a/Lib/importlib/test/source/test_finder.py +++ b/Lib/importlib/test/source/test_finder.py @@ -38,7 +38,7 @@ def import_(self, root, module): loader_details = [(_bootstrap.SourceFileLoader, _bootstrap._suffix_list(imp.PY_SOURCE), True), - (_bootstrap._SourcelessFileLoader, + (_bootstrap.SourcelessFileLoader, _bootstrap._suffix_list(imp.PY_COMPILED), True)] finder = _bootstrap.FileFinder(root, *loader_details) return finder.find_module(module) diff --git a/Lib/importlib/test/test_abc.py b/Lib/importlib/test/test_abc.py --- a/Lib/importlib/test/test_abc.py +++ b/Lib/importlib/test/test_abc.py @@ -62,7 +62,7 @@ class FileLoader(InheritanceTests, unittest.TestCase): superclasses = [abc.ResourceLoader, abc.ExecutionLoader] - subclasses = [machinery.SourceFileLoader, machinery._SourcelessFileLoader] + subclasses = [machinery.SourceFileLoader, machinery.SourcelessFileLoader] class SourceLoader(InheritanceTests, unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,7 +84,7 @@ which send EOF without trailing \r\n. - Issue #14605: Add importlib.abc.FileLoader, importlib.machinery.(FileFinder, - SourceFileLoader, _SourcelessFileLoader, ExtensionFileLoader). + SourceFileLoader, SourcelessFileLoader, ExtensionFileLoader). - Issue #13959: imp.cache_from_source()/source_from_cache() now follow os.path.join()/split() semantics for path manipulation instead of its prior, diff --git a/Python/importlib.h b/Python/importlib.h index bc4c0d9638e4f8f252a80b871ad40a9fa85bf97e..8bc0d8128cdbb869055d5c9ddfb53b6cbc17e32d GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 03:21:09 2012 From: python-checkins at python.org (eric.smith) Date: Wed, 25 Apr 2012 03:21:09 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Add_placeholder_section_for_pa?= =?utf8?q?ckaging_implications=2E?= Message-ID: http://hg.python.org/peps/rev/c097f8acf44d changeset: 4305:c097f8acf44d user: Eric V. Smith date: Tue Apr 24 21:21:04 2012 -0400 summary: Add placeholder section for packaging implications. files: pep-0420.txt | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -188,6 +188,11 @@ (These need to be addressed here.) +Package Implications +==================== + +(Placeholder) + References ========== -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Wed Apr 25 05:39:42 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 25 Apr 2012 05:39:42 +0200 Subject: [Python-checkins] Daily reference leaks (a2cf07135e4f): sum=6 Message-ID: results for a2cf07135e4f on branch "default" -------------------------------------------- test_tempfile leaked [2, 2, 2] references, sum=6 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog7puVpR', '-x'] From ncoghlan at gmail.com Wed Apr 25 08:12:38 2012 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 25 Apr 2012 16:12:38 +1000 Subject: [Python-checkins] peps: Note that ImportError will no longer be raised due to a missing __init__.py In-Reply-To: References: Message-ID: On Wed, Apr 25, 2012 at 2:56 AM, Jim Jewett wrote: > On Thu, Apr 19, 2012 at 18:56, eric.smith wrote: > >> +Note that an ImportError will no longer be raised for a directory >> +lacking an ``__init__.py`` file. Such a directory will now be imported >> +as a namespace package, whereas in prior Python versions an >> +ImportError would be raised. > > Given that there is no way to modify the __path__ of a namespace > package (short of restarting python?), *should* it be an error if > there is exactly one directory? > > Or is that just a case of "other tools out there, didn't happen to > install them"? Or you installed all of them into the same directory (as distro packages are likely to do). Also, a namespace package __path__ is still just a list - quite amenable to modification after creation. The only thing we're not currently promising in PEP 420 is a programmatic interface to redo the scan. Cheers, Nick. -- Nick Coghlan?? |?? ncoghlan at gmail.com?? |?? Brisbane, Australia From python-checkins at python.org Wed Apr 25 10:54:57 2012 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 25 Apr 2012 10:54:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605_and_=2314642?= =?utf8?q?=3A?= Message-ID: http://hg.python.org/cpython/rev/acfdf46b8de1 changeset: 76549:acfdf46b8de1 user: Marc-Andre Lemburg date: Wed Apr 25 10:54:48 2012 +0200 summary: Issue #14605 and #14642: Issue a warning in case Python\importlib.h needs to be rebuilt, but there's no Python interpreter around to freeze the bootstrap script. files: Lib/importlib/_bootstrap.py | 7 +++++++ Python/importlib.h | Bin 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -6,6 +6,13 @@ work. One should use importlib as the public-facing version of this module. """ +# +# IMPORTANT: Whenever making changes to this module, be sure to run +# a top-level make in order to get the frozen version of the module +# update. Not doing so, will result in the Makefile to fail for +# all others who don't have a ./python around to freeze the module +# in the early stages of compilation. +# # See importlib._setup() for what is injected into the global namespace. diff --git a/Python/importlib.h b/Python/importlib.h index 8bc0d8128cdbb869055d5c9ddfb53b6cbc17e32d..9dbd8816f3060d4ea66d3db7b1980139214e3908 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 11:51:46 2012 From: python-checkins at python.org (vinay.sajip) Date: Wed, 25 Apr 2012 11:51:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Fixed_test_to_w?= =?utf8?q?ork_on_Windows=2E?= Message-ID: http://hg.python.org/cpython/rev/8b8b580e3fd3 changeset: 76550:8b8b580e3fd3 branch: 2.7 parent: 76543:9cfe6845b1df user: Vinay Sajip date: Wed Apr 25 10:45:27 2012 +0100 summary: Fixed test to work on Windows. files: Lib/test/test_logging.py | 34 ++++++++++++++-------------- 1 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1888,28 +1888,28 @@ pass time.sleep(0.004 * random.randint(0, 4)) - def cleanup(remover, fn, handler): - handler.close() - remover.join() - if os.path.exists(fn): - os.unlink(fn) + del_count = 500 + log_count = 500 - fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') - os.close(fd) - del_count = 1000 - log_count = 1000 - remover = threading.Thread(target=remove_loop, args=(fn, del_count)) - remover.daemon = True - remover.start() for delay in (False, True): + fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') + os.close(fd) + remover = threading.Thread(target=remove_loop, args=(fn, del_count)) + remover.daemon = True + remover.start() h = logging.handlers.WatchedFileHandler(fn, delay=delay) - self.addCleanup(cleanup, remover, fn, h) f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') h.setFormatter(f) - for _ in range(log_count): - time.sleep(0.005) - r = logging.makeLogRecord({'msg': 'testing' }) - h.handle(r) + try: + for _ in range(log_count): + time.sleep(0.005) + r = logging.makeLogRecord({'msg': 'testing' }) + h.handle(r) + finally: + h.close() + remover.join() + if os.path.exists(fn): + os.unlink(fn) # Set the locale to the platform-dependent default. I have no idea -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 11:51:47 2012 From: python-checkins at python.org (vinay.sajip) Date: Wed, 25 Apr 2012 11:51:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Fixed_test_to_w?= =?utf8?q?ork_on_Windows=2E?= Message-ID: http://hg.python.org/cpython/rev/59bc2d9497b0 changeset: 76551:59bc2d9497b0 branch: 3.2 parent: 76544:5de7c3d64f2a user: Vinay Sajip date: Wed Apr 25 10:47:00 2012 +0100 summary: Fixed test to work on Windows. files: Lib/test/test_logging.py | 34 ++++++++++++++-------------- 1 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -2342,28 +2342,28 @@ pass time.sleep(0.004 * random.randint(0, 4)) - def cleanup(remover, fn, handler): - handler.close() - remover.join() - if os.path.exists(fn): - os.unlink(fn) + del_count = 500 + log_count = 500 - fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') - os.close(fd) - del_count = 1000 - log_count = 1000 - remover = threading.Thread(target=remove_loop, args=(fn, del_count)) - remover.daemon = True - remover.start() for delay in (False, True): + fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') + os.close(fd) + remover = threading.Thread(target=remove_loop, args=(fn, del_count)) + remover.daemon = True + remover.start() h = logging.handlers.WatchedFileHandler(fn, delay=delay) - self.addCleanup(cleanup, remover, fn, h) f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') h.setFormatter(f) - for _ in range(log_count): - time.sleep(0.005) - r = logging.makeLogRecord({'msg': 'testing' }) - h.handle(r) + try: + for _ in range(log_count): + time.sleep(0.005) + r = logging.makeLogRecord({'msg': 'testing' }) + h.handle(r) + finally: + h.close() + remover.join() + if os.path.exists(fn): + os.unlink(fn) # Set the locale to the platform-dependent default. I have no idea -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 11:51:48 2012 From: python-checkins at python.org (vinay.sajip) Date: Wed, 25 Apr 2012 11:51:48 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merged_fixed_test_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/8965693ecb14 changeset: 76552:8965693ecb14 parent: 76549:acfdf46b8de1 parent: 76551:59bc2d9497b0 user: Vinay Sajip date: Wed Apr 25 10:51:35 2012 +0100 summary: Merged fixed test from 3.2. files: Lib/test/test_logging.py | 36 ++++++++++++++-------------- 1 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -593,28 +593,28 @@ pass time.sleep(0.004 * random.randint(0, 4)) - def cleanup(remover, fn, handler): - handler.close() - remover.join() - if os.path.exists(fn): - os.unlink(fn) - - fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') - os.close(fd) - del_count = 1000 - log_count = 1000 - remover = threading.Thread(target=remove_loop, args=(fn, del_count)) - remover.daemon = True - remover.start() + del_count = 500 + log_count = 500 + for delay in (False, True): + fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') + os.close(fd) + remover = threading.Thread(target=remove_loop, args=(fn, del_count)) + remover.daemon = True + remover.start() h = logging.handlers.WatchedFileHandler(fn, delay=delay) - self.addCleanup(cleanup, remover, fn, h) f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') h.setFormatter(f) - for _ in range(log_count): - time.sleep(0.005) - r = logging.makeLogRecord({'msg': 'testing' }) - h.handle(r) + try: + for _ in range(log_count): + time.sleep(0.005) + r = logging.makeLogRecord({'msg': 'testing' }) + h.handle(r) + finally: + h.close() + remover.join() + if os.path.exists(fn): + os.unlink(fn) class BadStream(object): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 14:18:10 2012 From: python-checkins at python.org (nick.coghlan) Date: Wed, 25 Apr 2012 14:18:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Start_a_shared_utility_scri?= =?utf8?q?pt_for_poking_around_at_the_import_internals?= Message-ID: http://hg.python.org/cpython/rev/e91a8467328b changeset: 76553:e91a8467328b user: Nick Coghlan date: Wed Apr 25 22:17:54 2012 +1000 summary: Start a shared utility script for poking around at the import internals files: Tools/scripts/import_diagnostics.py | 39 +++++++++++++++++ 1 files changed, 39 insertions(+), 0 deletions(-) diff --git a/Tools/scripts/import_diagnostics.py b/Tools/scripts/import_diagnostics.py new file mode 100755 --- /dev/null +++ b/Tools/scripts/import_diagnostics.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Miscellaneous diagnostics for the import system""" + +import sys +import argparse +from pprint import pprint + +def _dump_state(args): + print(sys.version) + print("sys.path:") + pprint(sys.path) + print("sys.meta_path") + pprint(sys.meta_path) + print("sys.path_hooks") + pprint(sys.path_hooks) + print("sys.path_importer_cache") + pprint(sys.path_importer_cache) + print("sys.modules:") + pprint(sys.modules) + +COMMANDS = ( + ("dump", "Dump import state", _dump_state), +) + +def _make_parser(): + parser = argparse.ArgumentParser() + sub = parser.add_subparsers(title="Commands") + for name, description, implementation in COMMANDS: + cmd = sub.add_parser(name, help=description) + cmd.set_defaults(command=implementation) + return parser + +def main(args): + parser = _make_parser() + args = parser.parse_args(args) + return args.command(args) + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 15:00:36 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 25 Apr 2012 15:00:36 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NjY0?= =?utf8?q?=3A_It_is_now_possible_to_use_=40unittest=2Eskip=7BIf=2CUnless?= =?utf8?q?=7D_on_a_test?= Message-ID: http://hg.python.org/cpython/rev/ab3df6979bd0 changeset: 76554:ab3df6979bd0 branch: 3.2 parent: 76551:59bc2d9497b0 user: Antoine Pitrou date: Wed Apr 25 14:56:46 2012 +0200 summary: Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a test class that doesn't inherit from TestCase (i.e. a mixin). files: Lib/unittest/case.py | 2 +- Lib/unittest/test/test_skipping.py | 15 +++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 19 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -62,7 +62,7 @@ Unconditionally skip a test. """ def decorator(test_item): - if not (isinstance(test_item, type) and issubclass(test_item, TestCase)): + if not isinstance(test_item, type): @functools.wraps(test_item) def skip_wrapper(*args, **kwargs): raise SkipTest(reason) 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 @@ -66,6 +66,21 @@ self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(record, []) + def test_skip_non_unittest_class(self): + @unittest.skip("testing") + class Mixin: + def test_1(self): + record.append(1) + class Foo(Mixin, unittest.TestCase): + pass + record = [] + result = unittest.TestResult() + test = Foo("test_1") + suite = unittest.TestSuite([test]) + suite.run(result) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(record, []) + def test_expected_failure(self): class Foo(unittest.TestCase): @unittest.expectedFailure diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,9 @@ Library ------- +- Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a + test class that doesn't inherit from TestCase (i.e. a mixin). + - Issue #14160: TarFile.extractfile() failed to resolve symbolic links when the links were not located in an archive subdirectory. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 15:00:37 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 25 Apr 2012 15:00:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314664=3A_It_is_now_possible_to_use_=40unittest=2Esk?= =?utf8?q?ip=7BIf=2CUnless=7D_on_a_test?= Message-ID: http://hg.python.org/cpython/rev/188b96e0ea89 changeset: 76555:188b96e0ea89 parent: 76553:e91a8467328b parent: 76554:ab3df6979bd0 user: Antoine Pitrou date: Wed Apr 25 14:58:17 2012 +0200 summary: Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a test class that doesn't inherit from TestCase (i.e. a mixin). files: Lib/unittest/case.py | 2 +- Lib/unittest/test/test_skipping.py | 15 +++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 19 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -61,7 +61,7 @@ Unconditionally skip a test. """ def decorator(test_item): - if not (isinstance(test_item, type) and issubclass(test_item, TestCase)): + if not isinstance(test_item, type): @functools.wraps(test_item) def skip_wrapper(*args, **kwargs): raise SkipTest(reason) 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 @@ -66,6 +66,21 @@ self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(record, []) + def test_skip_non_unittest_class(self): + @unittest.skip("testing") + class Mixin: + def test_1(self): + record.append(1) + class Foo(Mixin, unittest.TestCase): + pass + record = [] + result = unittest.TestResult() + test = Foo("test_1") + suite = unittest.TestSuite([test]) + suite.run(result) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(record, []) + def test_expected_failure(self): class Foo(unittest.TestCase): @unittest.expectedFailure diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -71,6 +71,9 @@ Library ------- +- Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a + test class that doesn't inherit from TestCase (i.e. a mixin). + - Issue #4892: multiprocessing Connections can now be transferred over multiprocessing Connections. Patch by Richard Oudkerk (sbt). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 15:13:08 2012 From: python-checkins at python.org (brian.curtin) Date: Wed, 25 Apr 2012 15:13:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_=233561=2E_Add_an_optio?= =?utf8?q?n_to_place_the_Python_installation_into_the_Windows_Path?= Message-ID: http://hg.python.org/cpython/rev/4e9f1017355f changeset: 76556:4e9f1017355f user: Brian Curtin date: Wed Apr 25 08:12:37 2012 -0500 summary: Fix #3561. Add an option to place the Python installation into the Windows Path environment variable. files: Misc/NEWS | 3 +++ Tools/msi/msi.py | 22 +++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -189,6 +189,9 @@ Tools / Demos ------------- +- Issue #3561: The Windows installer now has an option, off by default, for + placing the Python installation into the system "Path" environment variable. + - Issue #13165: stringbench is now available in the Tools/stringbench folder. It used to live in its own SVN project. diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py --- a/Tools/msi/msi.py +++ b/Tools/msi/msi.py @@ -454,6 +454,10 @@ ("SetDLLDirToTarget", 'DLLDIR=""', 751), ]) + # Prepend TARGETDIR to the system path, and remove it on uninstall. + add_data(db, "Environment", + [("PathAddition", "=-*Path", "[TARGETDIR];[~]", "REGISTRY.path")]) + # Execute Sequences add_data(db, "InstallExecuteSequence", [("InitialTargetDir", 'TARGETDIR=""', 750), @@ -677,11 +681,11 @@ c=features.xbutton("Advanced", "Advanced", None, 0.30) c.event("SpawnDialog", "AdvancedDlg") - c=features.text("ItemDescription", 140, 180, 210, 30, 3, + c=features.text("ItemDescription", 140, 180, 210, 40, 3, "Multiline description of the currently selected item.") c.mapping("SelectionDescription","Text") - c=features.text("ItemSize", 140, 210, 210, 45, 3, + c=features.text("ItemSize", 140, 225, 210, 33, 3, "The size of the currently selected item.") c.mapping("SelectionSize", "Text") @@ -835,7 +839,7 @@ # (i.e. additional Python libraries) need to follow the parent feature. # Features that have no advertisement trigger (e.g. the test suite) # must not support advertisement - global default_feature, tcltk, htmlfiles, tools, testsuite, ext_feature, private_crt + global default_feature, tcltk, htmlfiles, tools, testsuite, ext_feature, private_crt, prepend_path default_feature = Feature(db, "DefaultFeature", "Python", "Python Interpreter and Libraries", 1, directory = "TARGETDIR") @@ -860,6 +864,15 @@ testsuite = Feature(db, "Testsuite", "Test suite", "Python test suite (Lib/test/)", 11, parent = default_feature, attributes=2|8) + # prepend_path is an additional feature which is to be off by default. + # Since the default level for the above features is 1, this needs to be + # at least level higher. + prepend_path = Feature(db, "PrependPath", "Add python.exe to Path", + "Prepend [TARGETDIR] to the system Path variable. " + "This allows you to type 'python' into a command " + "prompt without needing the full path.", 13, + parent = default_feature, attributes=2|8, + level=2) def extract_msvcr90(): # Find the redistributable files @@ -1146,6 +1159,8 @@ "InstallPath"), ("REGISTRY.doc", msilib.gen_uuid(), "TARGETDIR", registry_component, None, "Documentation"), + ("REGISTRY.path", msilib.gen_uuid(), "TARGETDIR", registry_component, None, + None), ("REGISTRY.def", msilib.gen_uuid(), "TARGETDIR", registry_component, None, None)] + tcldata) # See "FeatureComponents Table". @@ -1162,6 +1177,7 @@ add_data(db, "FeatureComponents", [(default_feature.id, "REGISTRY"), (htmlfiles.id, "REGISTRY.doc"), + (prepend_path.id, "REGISTRY.path"), (ext_feature.id, "REGISTRY.def")] + tcldata ) -- Repository URL: http://hg.python.org/cpython From brian at python.org Wed Apr 25 15:34:39 2012 From: brian at python.org (Brian Curtin) Date: Wed, 25 Apr 2012 08:34:39 -0500 Subject: [Python-checkins] cpython: Fix #3561. Add an option to place the Python installation into the Windows Path In-Reply-To: References: Message-ID: On Wed, Apr 25, 2012 at 08:13, brian.curtin wrote: > http://hg.python.org/cpython/rev/4e9f1017355f > changeset: ? 76556:4e9f1017355f > user: ? ? ? ?Brian Curtin > date: ? ? ? ?Wed Apr 25 08:12:37 2012 -0500 > summary: > ?Fix #3561. Add an option to place the Python installation into the Windows Path environment variable. > > files: > ?Misc/NEWS ? ? ? ?| ? 3 +++ > ?Tools/msi/msi.py | ?22 +++++++++++++++++++--- > ?2 files changed, 22 insertions(+), 3 deletions(-) http://bugs.python.org/issue14668 was created for updating the relevant documentation. I pushed without docs since it's unlikely they'll be done before the weekend's alpha 3 build, and I didn't want to have this feature wait an extra month before anyone sees it. Anyone who's installing an alpha build is probably advanced enough to know what it's doing in the meantime. From python-checkins at python.org Wed Apr 25 17:32:39 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 25 Apr 2012 17:32:39 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NjY0?= =?utf8?q?=3A_It_is_now_possible_to_use_=40unittest=2Eskip=7BIf=2CUnless?= =?utf8?q?=7D_on_a_test?= Message-ID: http://hg.python.org/cpython/rev/8a8d2f05068a changeset: 76557:8a8d2f05068a branch: 2.7 parent: 76550:8b8b580e3fd3 user: Antoine Pitrou date: Wed Apr 25 17:31:12 2012 +0200 summary: Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a test class that doesn't inherit from TestCase (i.e. a mixin). files: Lib/unittest/case.py | 3 +- Lib/unittest/test/test_skipping.py | 30 ++++++++++++++++++ Misc/NEWS | 3 + 3 files changed, 35 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -6,6 +6,7 @@ import difflib import pprint import re +import types import warnings from . import result @@ -55,7 +56,7 @@ Unconditionally skip a test. """ def decorator(test_item): - if not (isinstance(test_item, type) and issubclass(test_item, TestCase)): + if not isinstance(test_item, (type, types.ClassType)): @functools.wraps(test_item) def skip_wrapper(*args, **kwargs): raise SkipTest(reason) 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 @@ -66,6 +66,36 @@ self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(record, []) + def test_skip_non_unittest_class_old_style(self): + @unittest.skip("testing") + class Mixin: + def test_1(self): + record.append(1) + class Foo(Mixin, unittest.TestCase): + pass + record = [] + result = unittest.TestResult() + test = Foo("test_1") + suite = unittest.TestSuite([test]) + suite.run(result) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(record, []) + + def test_skip_non_unittest_class_new_style(self): + @unittest.skip("testing") + class Mixin(object): + def test_1(self): + record.append(1) + class Foo(Mixin, unittest.TestCase): + pass + record = [] + result = unittest.TestResult() + test = Foo("test_1") + suite = unittest.TestSuite([test]) + suite.run(result) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(record, []) + def test_expected_failure(self): class Foo(unittest.TestCase): @unittest.expectedFailure diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,9 @@ Library ------- +- Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a + test class that doesn't inherit from TestCase (i.e. a mixin). + - Issue #14160: TarFile.extractfile() failed to resolve symbolic links when the links were not located in an archive subdirectory. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 19:28:27 2012 From: python-checkins at python.org (eric.smith) Date: Wed, 25 Apr 2012 19:28:27 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Flesh_out_packaging_implicatio?= =?utf8?q?ns_section=2E?= Message-ID: http://hg.python.org/peps/rev/2cbb085e77e5 changeset: 4306:2cbb085e77e5 user: Eric V. Smith date: Wed Apr 25 13:28:21 2012 -0400 summary: Flesh out packaging implications section. files: pep-0420.txt | 26 +++++++++++++++++++++++--- 1 files changed, 23 insertions(+), 3 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -188,10 +188,30 @@ (These need to be addressed here.) -Package Implications -==================== +Packaging Implications +====================== -(Placeholder) +Multiple portions of a namespace package can be installed into the +same location, or into separate locations. For this section, suppose +there are two portions which define "foo.bar" and "foo.baz". "foo" +itself is a namespace package. + +If these are installed in the same location, a single directory "foo" +would be in a directory that is on ``sys.path``. Inside "foo" would be +two directories, "bar" and "baz". If "foo.bar" is removed (perhaps by +an automatic packager), care must be taken not to remove the "foo/baz" +or "foo" directories. Note that in this case "foo" will be a namespace +package (because it lacks an ``__init__.py``, even though all of its +portions are in the same directory. + +If the portions are installed in different locations, two different +"foo" directories would be in directories that are on +``sys.path``. "foo/bar" would be in one of these sys.path entries, and +"foo/baz" would be in the other. Upon removal of "foo.bar", the +"foo/bar" and corresonding "foo" directories can be removed. + +Note that even if they are installed in the same directory, "foo.bar" +and "foo.baz" would not have any files in common. References ========== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 25 19:33:31 2012 From: python-checkins at python.org (eric.smith) Date: Wed, 25 Apr 2012 19:33:31 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Put_two_spaces_after_the_end_o?= =?utf8?q?f_sentences=2C_so_that_emacs_does_a_better_job_at?= Message-ID: http://hg.python.org/peps/rev/3eeaa9f2acbf changeset: 4307:3eeaa9f2acbf user: Eric V. Smith date: Wed Apr 25 13:33:23 2012 -0400 summary: Put two spaces after the end of sentences, so that emacs does a better job at reflowing text. files: pep-0420.txt | 90 ++++++++++++++++++++-------------------- 1 files changed, 45 insertions(+), 45 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -14,12 +14,12 @@ ======== Namespace packages are a mechanism for splitting a single Python -package across multiple directories on disk. In current Python +package across multiple directories on disk. In current Python versions, an algorithm to compute the packages ``__path__`` must be -formulated. With the enhancement proposed here, the import machinery +formulated. With the enhancement proposed here, the import machinery itself will construct the list of directories that make up the package. This PEP builds upon the work started in rejected PEPs 382 -and 402. An implementation of this PEP is at [1]_. +and 402. An implementation of this PEP is at [1]_. Terminology =========== @@ -44,19 +44,19 @@ Namespace packages today ======================== -Python currently provides ``pkgutil.extend_path`` to denote a package as -a namespace package. The recommended way of using it is to put:: +Python currently provides ``pkgutil.extend_path`` to denote a package +as a namespace package. The recommended way of using it is to put:: from pkgutil import extend_path __path__ = extend_path(__path__, __name__) -in the package's ``__init__.py``. Every distribution needs to provide +in the package's ``__init__.py``. Every distribution needs to provide the same contents in its ``__init__.py``, so that ``extend_path`` is invoked independent of which portion of the package gets imported -first. As a consequence, the package's ``__init__.py`` cannot +first. As a consequence, the package's ``__init__.py`` cannot practically define any names as it depends on the order of the package fragments on ``sys.path`` to determine which portion is imported -first. As a special feature, ``extend_path`` reads files named +first. As a special feature, ``extend_path`` reads files named ``.pkg`` which allows declaration of additional portions. setuptools provides a similar function named @@ -67,7 +67,7 @@ In the portion's ``__init__.py``, no assignment to ``__path__`` is necessary, as ``declare_namespace`` modifies the package ``__path__`` -through ``sys.modules``. As a special feature, ``declare_namespace`` +through ``sys.modules``. As a special feature, ``declare_namespace`` also supports zip files, and registers the package name internally so that future additions to ``sys.path`` by setuptools can properly add additional portions to each package. @@ -81,8 +81,8 @@ The current imperative approach to namespace packages has lead to multiple slightly-incompatible mechanisms for providing namespace -packages. For example, pkgutil supports ``*.pkg`` files; setuptools -doesn't. Likewise, setuptools supports inspecting zip files, and +packages. For example, pkgutil supports ``*.pkg`` files; setuptools +doesn't. Likewise, setuptools supports inspecting zip files, and supports adding portions to its ``_namespace_packages`` variable, whereas pkgutil doesn't. @@ -90,12 +90,12 @@ directories (and hence found via multiple ``sys.path`` entries). In this configuration, it doesn't matter if multiple portions all provide an ``__init__.py`` file, so long as each portion correctly initializes -the namespace package. However, Linux distribution vendors (amongst +the namespace package. However, Linux distribution vendors (amongst others) prefer to combine the separate portions and install them all -into the *same* filesystem directory. This creates a potential for +into the *same* filesystem directory. This creates a potential for conflict, as the portions are now attempting to provide the *same* file on the target system - something that is not allowed by many -package managers. Allowing implicit namespace packages means that the +package managers. Allowing implicit namespace packages means that the requirement to provide an ``__init__.py`` file can be dropped completely, and affected portions can be installed into a common directory or split across multiple directories as distributions see @@ -107,14 +107,14 @@ Regular packages will continue to have an ``__init__.py`` and will reside in a single directory. -Namespace packages cannot contain an ``__init__.py``. As a +Namespace packages cannot contain an ``__init__.py``. As a consequence, ``pkgutil.extend_path`` and ``pkg_resources.declare_namespace`` become obsolete for purposes of -namespace package creation. There will be no marker file or directory +namespace package creation. There will be no marker file or directory for specifing a namespace package. During import processing, the import machinery will continue to -iterate over the parent path as it does in Python 3.2. While looking +iterate over the parent path as it does in Python 3.2. While looking for a module or package named "foo": * If ``foo/__init__.py`` is found, a regular package is imported. @@ -122,7 +122,7 @@ * If not, but ``foo`` is found and is a directory, it is recorded. If the scan along the parent path completes without finding a module -or package, then a namespace package is created. The new namespace +or package, then a namespace package is created. The new namespace package: * Has a ``__file__`` attribute set to the first directory that was @@ -132,47 +132,47 @@ There is no mechanism to automatically recompute the ``__path__`` if ``sys.path`` is altered after a namespace package has already been -created. However, existing namespace utilities (like +created. However, existing namespace utilities (like ``pkgutil.extend_path``) can be used to update them explicitly if desired. Note that if "import foo" is executed and "foo" is found as a namespace package (using the above rules), then "foo" is immediately -created as a package. The creation of the namespace package is not +created as a package. The creation of the namespace package is not deferred until a sub-level import occurs. Impact on Import Finders and Loaders ------------------------------------ -PEP 302 defines "finders" that are called to search path -elements. These finders' ``find_module`` methods currently return -either a "loader" object or None. For a finder to contribute to -namespace packages, ``find_module`` will return a third type: a -string. This is the string that will be recorded and later used as a -component of the namespace module's __path__, as described above. +PEP 302 defines "finders" that are called to search path elements. +These finders' ``find_module`` methods currently return either a +"loader" object or None. For a finder to contribute to namespace +packages, ``find_module`` will return a third type: a string. This is +the string that will be recorded and later used as a component of the +namespace module's __path__, as described above. [Consider Brett's idea to pass NamespaceLoader in to PathFinder] Discussion ========== -There is no intention to remove support of regular packages. If there +There is no intention to remove support of regular packages. If there is no intention that a package is a namespace package, then there is a -performance advantage to it being a regular package. Creation and +performance advantage to it being a regular package. Creation and loading of the package can take place once it is located along the -path. With namespace packages, all entries in the path must be +path. With namespace packages, all entries in the path must be scanned. Note that an ImportWarning will no longer be raised for a directory -lacking an ``__init__.py`` file. Such a directory will now be imported -as a namespace package, whereas in prior Python versions an +lacking an ``__init__.py`` file. Such a directory will now be +imported as a namespace package, whereas in prior Python versions an ImportError would be raised. At PyCon 2012, we had a discussion about namespace packages at which PEP 382 and PEP 402 were rejected, to be replaced by this PEP [2]_. -Nick Coglan presented a list of his objections to this proposal -[3]_. They are: +Nick Coglan presented a list of his objections to this proposal [3]_. +They are: * Implicit package directories go against the Zen of Python @@ -192,23 +192,23 @@ ====================== Multiple portions of a namespace package can be installed into the -same location, or into separate locations. For this section, suppose -there are two portions which define "foo.bar" and "foo.baz". "foo" +same location, or into separate locations. For this section, suppose +there are two portions which define "foo.bar" and "foo.baz". "foo" itself is a namespace package. If these are installed in the same location, a single directory "foo" -would be in a directory that is on ``sys.path``. Inside "foo" would be -two directories, "bar" and "baz". If "foo.bar" is removed (perhaps by -an automatic packager), care must be taken not to remove the "foo/baz" -or "foo" directories. Note that in this case "foo" will be a namespace -package (because it lacks an ``__init__.py``, even though all of its -portions are in the same directory. +would be in a directory that is on ``sys.path``. Inside "foo" would +be two directories, "bar" and "baz". If "foo.bar" is removed (perhaps +by an automatic packager), care must be taken not to remove the +"foo/baz" or "foo" directories. Note that in this case "foo" will be +a namespace package (because it lacks an ``__init__.py``, even though +all of its portions are in the same directory. If the portions are installed in different locations, two different -"foo" directories would be in directories that are on -``sys.path``. "foo/bar" would be in one of these sys.path entries, and -"foo/baz" would be in the other. Upon removal of "foo.bar", the -"foo/bar" and corresonding "foo" directories can be removed. +"foo" directories would be in directories that are on ``sys.path``. +"foo/bar" would be in one of these sys.path entries, and "foo/baz" +would be in the other. Upon removal of "foo.bar", the "foo/bar" and +corresonding "foo" directories can be removed. Note that even if they are installed in the same directory, "foo.bar" and "foo.baz" would not have any files in common. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 25 19:35:15 2012 From: python-checkins at python.org (eric.smith) Date: Wed, 25 Apr 2012 19:35:15 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Fix_typo=2E?= Message-ID: http://hg.python.org/peps/rev/c6cbb3dac78a changeset: 4308:c6cbb3dac78a user: Eric V. Smith date: Wed Apr 25 13:35:07 2012 -0400 summary: Fix typo. files: pep-0420.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -201,7 +201,7 @@ be two directories, "bar" and "baz". If "foo.bar" is removed (perhaps by an automatic packager), care must be taken not to remove the "foo/baz" or "foo" directories. Note that in this case "foo" will be -a namespace package (because it lacks an ``__init__.py``, even though +a namespace package (because it lacks an ``__init__.py``), even though all of its portions are in the same directory. If the portions are installed in different locations, two different -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 25 19:45:28 2012 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 25 Apr 2012 19:45:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605_and_=2314642?= =?utf8?q?=3A_Issue_a_warning_in_case_Python=5Cimportlib=2Eh_needs_to?= Message-ID: http://hg.python.org/cpython/rev/5fea362b92fc changeset: 76558:5fea362b92fc parent: 76556:4e9f1017355f user: Marc-Andre Lemburg date: Wed Apr 25 19:45:11 2012 +0200 summary: Issue #14605 and #14642: Issue a warning in case Python\importlib.h needs to be rebuilt, but there's no Python interpreter around to freeze the bootstrap script. Forgot to include Makefile.pre.in in changeset 76549:acfdf46b8de1. files: Makefile.pre.in | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -573,12 +573,23 @@ Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) + ############################################################################ # Importlib Python/importlib.h: $(srcdir)/Lib/importlib/_bootstrap.py $(srcdir)/Python/freeze_importlib.py - ./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \ - $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h + @if test -f ./$(BUILDPYTHON); then \ + ./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \ + $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h; \ + else \ + echo "----------------------------------------------------------"; \ + echo "Python/importlib.h needs to be rebuilt, but no interpreter"; \ + echo "is available to do so. Leaving the previous version in"; \ + echo "place. You may want to run ''make'' a second time after"; \ + echo "this build is complete."; \ + echo "----------------------------------------------------------"; \ + fi + ############################################################################ # Special rules for object files -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Apr 25 19:52:40 2012 From: python-checkins at python.org (eric.smith) Date: Wed, 25 Apr 2012 19:52:40 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Add_a_note_that_a_namespace_pa?= =?utf8?q?ckage_is_not_a_different_type_of_package=2C_but_a?= Message-ID: http://hg.python.org/peps/rev/6eff72fe26b6 changeset: 4309:6eff72fe26b6 user: Eric V. Smith date: Wed Apr 25 13:52:33 2012 -0400 summary: Add a note that a namespace package is not a different type of package, but a new way of creating a package. files: pep-0420.txt | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -141,6 +141,14 @@ created as a package. The creation of the namespace package is not deferred until a sub-level import occurs. +A namespace package is not fundamentally different from a regular +package. It is just a different way of creating packages. Once a +namespace package is created, there is no functional difference +between it and a regular package. The only observable difference is +that the namespace package's ``__file__`` attribute will end with a +path separator (typically a slash or backslash, depending on the +platform). + Impact on Import Finders and Loaders ------------------------------------ -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Apr 25 19:57:14 2012 From: python-checkins at python.org (sandro.tosi) Date: Wed, 25 Apr 2012 19:57:14 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_fix_footnote_re?= =?utf8?q?ference=3B_thanks_to_Fizz_from_docs=40?= Message-ID: http://hg.python.org/cpython/rev/4b101df1e9f7 changeset: 76559:4b101df1e9f7 branch: 2.7 parent: 76557:8a8d2f05068a user: Sandro Tosi date: Wed Apr 25 19:55:30 2012 +0200 summary: fix footnote reference; thanks to Fizz from docs@ files: Doc/library/time.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -410,7 +410,7 @@ +-------+-------------------+---------------------------------+ | 4 | :attr:`tm_min` | range [0, 59] | +-------+-------------------+---------------------------------+ - | 5 | :attr:`tm_sec` | range [0, 61]; see **(1)** in | + | 5 | :attr:`tm_sec` | range [0, 61]; see **(2)** in | | | | :func:`strftime` description | +-------+-------------------+---------------------------------+ | 6 | :attr:`tm_wday` | range [0, 6], Monday is 0 | -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 00:38:36 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 26 Apr 2012 00:38:36 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_long=5Fto=5Fdecimal=5Fstrin?= =?utf8?q?g=28=29_and_=5FPyLong=5FFormat=28=29_check_the_consistency_of_ne?= =?utf8?q?wly?= Message-ID: http://hg.python.org/cpython/rev/3bdcf0cab164 changeset: 76560:3bdcf0cab164 parent: 76558:5fea362b92fc user: Victor Stinner date: Thu Apr 26 00:37:21 2012 +0200 summary: long_to_decimal_string() and _PyLong_Format() check the consistency of newly created strings using _PyUnicode_CheckConsistency() in debug mode files: Objects/longobject.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1657,6 +1657,7 @@ /* check we've counted correctly */ assert(p == PyUnicode_1BYTE_DATA(str)); + assert(_PyUnicode_CheckConsistency(str, 1)); Py_DECREF(scratch); return (PyObject *)str; } @@ -1761,6 +1762,7 @@ if (negative) *--p = '-'; assert(p == PyUnicode_1BYTE_DATA(v)); + assert(_PyUnicode_CheckConsistency(v, 1)); return v; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 00:40:34 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 26 Apr 2012 00:40:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_=5FPyUnicode=5FCheckConsist?= =?utf8?q?ency=28=29_ensures_that_the_unicode_string_ends_with_a?= Message-ID: http://hg.python.org/cpython/rev/004f8d96f573 changeset: 76561:004f8d96f573 user: Victor Stinner date: Thu Apr 26 00:39:37 2012 +0200 summary: _PyUnicode_CheckConsistency() ensures that the unicode string ends with a null character files: Objects/unicodeobject.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -375,10 +375,13 @@ { Py_ssize_t i; Py_UCS4 maxchar = 0; - void *data = PyUnicode_DATA(ascii); + void *data; + Py_UCS4 ch; + + data = PyUnicode_DATA(ascii); for (i=0; i < ascii->length; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); + ch = PyUnicode_READ(kind, data, i); if (ch > maxchar) maxchar = ch; } @@ -398,6 +401,7 @@ assert(maxchar >= 0x10000); assert(maxchar <= MAX_UNICODE); } + assert(PyUnicode_READ(kind, data, ascii->length) == 0); } return 1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 02:19:04 2012 From: python-checkins at python.org (brett.cannon) Date: Thu, 26 Apr 2012 02:19:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Insert_to?= =?utf8?q?_the_front_of_sys=2Epath=5Fhooks_instead_of_appending=2E?= Message-ID: http://hg.python.org/cpython/rev/8dab93ec19de changeset: 76562:8dab93ec19de parent: 76548:a2cf07135e4f user: Brett Cannon date: Tue Apr 24 22:03:46 2012 -0400 summary: Issue #14605: Insert to the front of sys.path_hooks instead of appending. files: Lib/test/test_importhooks.py | 4 ++-- Lib/test/test_threaded_import.py | 2 +- Python/import.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_importhooks.py b/Lib/test/test_importhooks.py --- a/Lib/test/test_importhooks.py +++ b/Lib/test/test_importhooks.py @@ -215,7 +215,7 @@ self.doTestImports(i) def testPathHook(self): - sys.path_hooks.append(PathImporter) + sys.path_hooks.insert(0, PathImporter) sys.path.append(test_path) self.doTestImports() @@ -228,7 +228,7 @@ def testImpWrapper(self): i = ImpWrapper() sys.meta_path.append(i) - sys.path_hooks.append(ImpWrapper) + sys.path_hooks.insert(0, ImpWrapper) mnames = ( "colorsys", "urllib.parse", "distutils.core", "sys", ) diff --git a/Lib/test/test_threaded_import.py b/Lib/test/test_threaded_import.py --- a/Lib/test/test_threaded_import.py +++ b/Lib/test/test_threaded_import.py @@ -145,7 +145,7 @@ def path_hook(path): finder.find_module('') raise ImportError - sys.path_hooks.append(path_hook) + sys.path_hooks.insert(0, path_hook) sys.meta_path.append(flushing_finder) try: # Flush the cache a first time diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -268,8 +268,8 @@ "# can't import zipimport.zipimporter\n"); } else { - /* sys.path_hooks.append(zipimporter) */ - err = PyList_Append(path_hooks, zipimporter); + /* sys.path_hooks.insert(0, zipimporter) */ + err = PyList_Insert(path_hooks, 0, zipimporter); Py_DECREF(zipimporter); if (err < 0) { goto error; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 02:19:05 2012 From: python-checkins at python.org (brett.cannon) Date: Thu, 26 Apr 2012 02:19:05 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_Merge?= Message-ID: http://hg.python.org/cpython/rev/37b03d64883a changeset: 76563:37b03d64883a parent: 76562:8dab93ec19de parent: 76561:004f8d96f573 user: Brett Cannon date: Wed Apr 25 20:18:24 2012 -0400 summary: Merge files: Lib/importlib/_bootstrap.py | 7 ++ Lib/test/test_logging.py | 36 +++++++------- Lib/unittest/case.py | 2 +- Lib/unittest/test/test_skipping.py | 15 ++++++ Makefile.pre.in | 15 +++++- Misc/NEWS | 6 ++ Objects/longobject.c | 2 + Objects/unicodeobject.c | 8 ++- Python/importlib.h | Bin Tools/msi/msi.py | 22 +++++++- Tools/scripts/import_diagnostics.py | 39 ++++++++++++++++ 11 files changed, 126 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 @@ -6,6 +6,13 @@ work. One should use importlib as the public-facing version of this module. """ +# +# IMPORTANT: Whenever making changes to this module, be sure to run +# a top-level make in order to get the frozen version of the module +# update. Not doing so, will result in the Makefile to fail for +# all others who don't have a ./python around to freeze the module +# in the early stages of compilation. +# # See importlib._setup() for what is injected into the global namespace. diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -593,28 +593,28 @@ pass time.sleep(0.004 * random.randint(0, 4)) - def cleanup(remover, fn, handler): - handler.close() - remover.join() - if os.path.exists(fn): - os.unlink(fn) - - fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') - os.close(fd) - del_count = 1000 - log_count = 1000 - remover = threading.Thread(target=remove_loop, args=(fn, del_count)) - remover.daemon = True - remover.start() + del_count = 500 + log_count = 500 + for delay in (False, True): + fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') + os.close(fd) + remover = threading.Thread(target=remove_loop, args=(fn, del_count)) + remover.daemon = True + remover.start() h = logging.handlers.WatchedFileHandler(fn, delay=delay) - self.addCleanup(cleanup, remover, fn, h) f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') h.setFormatter(f) - for _ in range(log_count): - time.sleep(0.005) - r = logging.makeLogRecord({'msg': 'testing' }) - h.handle(r) + try: + for _ in range(log_count): + time.sleep(0.005) + r = logging.makeLogRecord({'msg': 'testing' }) + h.handle(r) + finally: + h.close() + remover.join() + if os.path.exists(fn): + os.unlink(fn) class BadStream(object): diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -61,7 +61,7 @@ Unconditionally skip a test. """ def decorator(test_item): - if not (isinstance(test_item, type) and issubclass(test_item, TestCase)): + if not isinstance(test_item, type): @functools.wraps(test_item) def skip_wrapper(*args, **kwargs): raise SkipTest(reason) 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 @@ -66,6 +66,21 @@ self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(record, []) + def test_skip_non_unittest_class(self): + @unittest.skip("testing") + class Mixin: + def test_1(self): + record.append(1) + class Foo(Mixin, unittest.TestCase): + pass + record = [] + result = unittest.TestResult() + test = Foo("test_1") + suite = unittest.TestSuite([test]) + suite.run(result) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(record, []) + def test_expected_failure(self): class Foo(unittest.TestCase): @unittest.expectedFailure diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -573,12 +573,23 @@ Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) + ############################################################################ # Importlib Python/importlib.h: $(srcdir)/Lib/importlib/_bootstrap.py $(srcdir)/Python/freeze_importlib.py - ./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \ - $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h + @if test -f ./$(BUILDPYTHON); then \ + ./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \ + $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h; \ + else \ + echo "----------------------------------------------------------"; \ + echo "Python/importlib.h needs to be rebuilt, but no interpreter"; \ + echo "is available to do so. Leaving the previous version in"; \ + echo "place. You may want to run ''make'' a second time after"; \ + echo "this build is complete."; \ + echo "----------------------------------------------------------"; \ + fi + ############################################################################ # Special rules for object files diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -71,6 +71,9 @@ Library ------- +- Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a + test class that doesn't inherit from TestCase (i.e. a mixin). + - Issue #4892: multiprocessing Connections can now be transferred over multiprocessing Connections. Patch by Richard Oudkerk (sbt). @@ -186,6 +189,9 @@ Tools / Demos ------------- +- Issue #3561: The Windows installer now has an option, off by default, for + placing the Python installation into the system "Path" environment variable. + - Issue #13165: stringbench is now available in the Tools/stringbench folder. It used to live in its own SVN project. diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1657,6 +1657,7 @@ /* check we've counted correctly */ assert(p == PyUnicode_1BYTE_DATA(str)); + assert(_PyUnicode_CheckConsistency(str, 1)); Py_DECREF(scratch); return (PyObject *)str; } @@ -1761,6 +1762,7 @@ if (negative) *--p = '-'; assert(p == PyUnicode_1BYTE_DATA(v)); + assert(_PyUnicode_CheckConsistency(v, 1)); return v; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -375,10 +375,13 @@ { Py_ssize_t i; Py_UCS4 maxchar = 0; - void *data = PyUnicode_DATA(ascii); + void *data; + Py_UCS4 ch; + + data = PyUnicode_DATA(ascii); for (i=0; i < ascii->length; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); + ch = PyUnicode_READ(kind, data, i); if (ch > maxchar) maxchar = ch; } @@ -398,6 +401,7 @@ assert(maxchar >= 0x10000); assert(maxchar <= MAX_UNICODE); } + assert(PyUnicode_READ(kind, data, ascii->length) == 0); } return 1; } diff --git a/Python/importlib.h b/Python/importlib.h index 8bc0d8128cdbb869055d5c9ddfb53b6cbc17e32d..9dbd8816f3060d4ea66d3db7b1980139214e3908 GIT binary patch [stripped] diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py --- a/Tools/msi/msi.py +++ b/Tools/msi/msi.py @@ -454,6 +454,10 @@ ("SetDLLDirToTarget", 'DLLDIR=""', 751), ]) + # Prepend TARGETDIR to the system path, and remove it on uninstall. + add_data(db, "Environment", + [("PathAddition", "=-*Path", "[TARGETDIR];[~]", "REGISTRY.path")]) + # Execute Sequences add_data(db, "InstallExecuteSequence", [("InitialTargetDir", 'TARGETDIR=""', 750), @@ -677,11 +681,11 @@ c=features.xbutton("Advanced", "Advanced", None, 0.30) c.event("SpawnDialog", "AdvancedDlg") - c=features.text("ItemDescription", 140, 180, 210, 30, 3, + c=features.text("ItemDescription", 140, 180, 210, 40, 3, "Multiline description of the currently selected item.") c.mapping("SelectionDescription","Text") - c=features.text("ItemSize", 140, 210, 210, 45, 3, + c=features.text("ItemSize", 140, 225, 210, 33, 3, "The size of the currently selected item.") c.mapping("SelectionSize", "Text") @@ -835,7 +839,7 @@ # (i.e. additional Python libraries) need to follow the parent feature. # Features that have no advertisement trigger (e.g. the test suite) # must not support advertisement - global default_feature, tcltk, htmlfiles, tools, testsuite, ext_feature, private_crt + global default_feature, tcltk, htmlfiles, tools, testsuite, ext_feature, private_crt, prepend_path default_feature = Feature(db, "DefaultFeature", "Python", "Python Interpreter and Libraries", 1, directory = "TARGETDIR") @@ -860,6 +864,15 @@ testsuite = Feature(db, "Testsuite", "Test suite", "Python test suite (Lib/test/)", 11, parent = default_feature, attributes=2|8) + # prepend_path is an additional feature which is to be off by default. + # Since the default level for the above features is 1, this needs to be + # at least level higher. + prepend_path = Feature(db, "PrependPath", "Add python.exe to Path", + "Prepend [TARGETDIR] to the system Path variable. " + "This allows you to type 'python' into a command " + "prompt without needing the full path.", 13, + parent = default_feature, attributes=2|8, + level=2) def extract_msvcr90(): # Find the redistributable files @@ -1146,6 +1159,8 @@ "InstallPath"), ("REGISTRY.doc", msilib.gen_uuid(), "TARGETDIR", registry_component, None, "Documentation"), + ("REGISTRY.path", msilib.gen_uuid(), "TARGETDIR", registry_component, None, + None), ("REGISTRY.def", msilib.gen_uuid(), "TARGETDIR", registry_component, None, None)] + tcldata) # See "FeatureComponents Table". @@ -1162,6 +1177,7 @@ add_data(db, "FeatureComponents", [(default_feature.id, "REGISTRY"), (htmlfiles.id, "REGISTRY.doc"), + (prepend_path.id, "REGISTRY.path"), (ext_feature.id, "REGISTRY.def")] + tcldata ) diff --git a/Tools/scripts/import_diagnostics.py b/Tools/scripts/import_diagnostics.py new file mode 100755 --- /dev/null +++ b/Tools/scripts/import_diagnostics.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Miscellaneous diagnostics for the import system""" + +import sys +import argparse +from pprint import pprint + +def _dump_state(args): + print(sys.version) + print("sys.path:") + pprint(sys.path) + print("sys.meta_path") + pprint(sys.meta_path) + print("sys.path_hooks") + pprint(sys.path_hooks) + print("sys.path_importer_cache") + pprint(sys.path_importer_cache) + print("sys.modules:") + pprint(sys.modules) + +COMMANDS = ( + ("dump", "Dump import state", _dump_state), +) + +def _make_parser(): + parser = argparse.ArgumentParser() + sub = parser.add_subparsers(title="Commands") + for name, description, implementation in COMMANDS: + cmd = sub.add_parser(name, help=description) + cmd.set_defaults(command=implementation) + return parser + +def main(args): + parser = _make_parser() + args = parser.parse_args(args) + return args.command(args) + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 02:19:06 2012 From: python-checkins at python.org (brett.cannon) Date: Thu, 26 Apr 2012 02:19:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Update_importlib=2Eh?= Message-ID: http://hg.python.org/cpython/rev/c5ec907bcad2 changeset: 76564:c5ec907bcad2 user: Brett Cannon date: Wed Apr 25 20:18:55 2012 -0400 summary: Update importlib.h files: Python/importlib.h | Bin 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Python/importlib.h b/Python/importlib.h index 9dbd8816f3060d4ea66d3db7b1980139214e3908..991334e6316f63a1c5e7bd01307b045cffd9798e GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 02:49:34 2012 From: python-checkins at python.org (brett.cannon) Date: Thu, 26 Apr 2012 02:49:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Silence_DeprecationWarning_?= =?utf8?q?for_cgi=2Eescape=28=29_usage_in_test=5Fcgi=2E?= Message-ID: http://hg.python.org/cpython/rev/bc91c251a4e9 changeset: 76565:bc91c251a4e9 user: Brett Cannon date: Wed Apr 25 20:49:19 2012 -0400 summary: Silence DeprecationWarning for cgi.escape() usage in test_cgi. files: Lib/test/test_cgi.py | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-) 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 @@ -4,6 +4,7 @@ import sys import tempfile import unittest +import warnings from io import StringIO, BytesIO class HackedSysModule: @@ -119,9 +120,13 @@ class CgiTests(unittest.TestCase): def test_escape(self): - self.assertEqual("test & string", cgi.escape("test & string")) - self.assertEqual("<test string>", cgi.escape("")) - self.assertEqual(""test string"", cgi.escape('"test string"', True)) + # cgi.escape() is deprecated. + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', 'cgi\.escape', + DeprecationWarning) + self.assertEqual("test & string", cgi.escape("test & string")) + self.assertEqual("<test string>", cgi.escape("")) + self.assertEqual(""test string"", cgi.escape('"test string"', True)) def test_strict(self): for orig, expect in parse_strict_test_cases: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 02:55:22 2012 From: python-checkins at python.org (brett.cannon) Date: Thu, 26 Apr 2012 02:55:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Make_expl?= =?utf8?q?icit_the_entries_on_sys=2Epath=5Fhooks_that_used_to?= Message-ID: http://hg.python.org/cpython/rev/57d558f1904d changeset: 76566:57d558f1904d user: Brett Cannon date: Wed Apr 25 20:54:04 2012 -0400 summary: Issue #14605: Make explicit the entries on sys.path_hooks that used to be implicit. Added a warning for when sys.path_hooks is found to be empty. Also changed the meaning of None in sys.path_importer_cache to represent trying sys.path_hooks again (an interpretation of previous semantics). Also added a warning for when None was found. The long-term goal is for None in sys.path_importer_cache to represent the same as imp.NullImporter: no finder found for that sys.path entry. files: Lib/importlib/_bootstrap.py | 64 ++----- Lib/importlib/test/import_/test_fromlist.py | 4 +- Lib/importlib/test/import_/test_path.py | 82 ++------- Lib/pkgutil.py | 13 +- Lib/runpy.py | 12 +- Lib/test/test_cmd_line_script.py | 15 +- Misc/NEWS | 5 + Python/importlib.h | Bin Python/pythonrun.c | 2 +- 9 files changed, 71 insertions(+), 126 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -752,15 +752,15 @@ """Meta path finder for sys.(path|path_hooks|path_importer_cache).""" @classmethod - def _path_hooks(cls, path, hooks=None): + def _path_hooks(cls, path): """Search sequence of hooks for a finder for 'path'. If 'hooks' is false then use sys.path_hooks. """ - if hooks is None: - hooks = sys.path_hooks - for hook in hooks: + if not sys.path_hooks: + _warnings.warn('sys.path_hooks is empty', ImportWarning) + for hook in sys.path_hooks: try: return hook(path) except ImportError: @@ -770,14 +770,11 @@ path=path) @classmethod - def _path_importer_cache(cls, path, default=None): + def _path_importer_cache(cls, path): """Get the finder for the path from sys.path_importer_cache. If the path is not in the cache, find the appropriate finder and cache - it. If None is cached, get the default finder and cache that - (if applicable). - - Because of NullImporter, some finder should be returned. The only + it. Because of NullImporter, some finder should be returned. The only explicit fail case is if None is cached but the path cannot be used for the default hook, for which ImportError is raised. @@ -790,9 +787,13 @@ finder = cls._path_hooks(path) sys.path_importer_cache[path] = finder else: - if finder is None and default: - # Raises ImportError on failure. - finder = default(path) + if finder is None: + msg = ("'None' in sys.path_importer_cache[{!r}], so retrying " + "finder search; in future versions of Python 'None' " + "will represent no finder".format(path)) + _warnings.warn(msg, ImportWarning) + del sys.path_importer_cache[path] + finder = cls._path_hooks(path) sys.path_importer_cache[path] = finder return finder @@ -931,29 +932,6 @@ # Import itself ############################################################### -_DEFAULT_PATH_HOOK = None # Set in _setup() - -class _DefaultPathFinder(PathFinder): - - """Subclass of PathFinder that implements implicit semantics for - __import__.""" - - @classmethod - def _path_hooks(cls, path): - """Search sys.path_hooks as well as implicit path hooks.""" - try: - return super()._path_hooks(path) - except ImportError: - implicit_hooks = [_DEFAULT_PATH_HOOK, _imp.NullImporter] - return super()._path_hooks(path, implicit_hooks) - - @classmethod - def _path_importer_cache(cls, path): - """Use the default path hook when None is stored in - sys.path_importer_cache.""" - return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK) - - class _ImportLockContext: """Context manager for the import lock.""" @@ -1008,7 +986,7 @@ raise ValueError("Empty module name") -_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder] +_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, PathFinder] _ERR_MSG = 'No module named {!r}' @@ -1203,12 +1181,6 @@ if builtin_os == 'nt': SOURCE_SUFFIXES.append('.pyw') - supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), - (SourceFileLoader, _suffix_list(1), True), - (SourcelessFileLoader, _suffix_list(2), True)] - setattr(self_module, '_DEFAULT_PATH_HOOK', - FileFinder.path_hook(*supported_loaders)) - def _install(sys_module, _imp_module): """Install importlib as the implementation of import. @@ -1218,6 +1190,8 @@ """ _setup(sys_module, _imp_module) - orig_import = builtins.__import__ - builtins.__import__ = __import__ - builtins.__original_import__ = orig_import + supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), + (SourceFileLoader, _suffix_list(1), True), + (SourcelessFileLoader, _suffix_list(2), True)] + sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders), + _imp.NullImporter]) diff --git a/Lib/importlib/test/import_/test_fromlist.py b/Lib/importlib/test/import_/test_fromlist.py --- a/Lib/importlib/test/import_/test_fromlist.py +++ b/Lib/importlib/test/import_/test_fromlist.py @@ -1,6 +1,7 @@ """Test that the semantics relating to the 'fromlist' argument are correct.""" from .. import util from . import util as import_util +import imp import unittest class ReturnValue(unittest.TestCase): @@ -73,7 +74,8 @@ def test_no_module_from_package(self): # [no module] with util.mock_modules('pkg.__init__') as importer: - with util.import_state(meta_path=[importer]): + with util.import_state(meta_path=[importer], + path_hooks=[imp.NullImporter]): module = import_util.import_('pkg', fromlist='non_existent') self.assertEqual(module.__name__, 'pkg') self.assertTrue(not hasattr(module, 'non_existent')) diff --git a/Lib/importlib/test/import_/test_path.py b/Lib/importlib/test/import_/test_path.py --- a/Lib/importlib/test/import_/test_path.py +++ b/Lib/importlib/test/import_/test_path.py @@ -9,6 +9,7 @@ from test import support from types import MethodType import unittest +import warnings class FinderTests(unittest.TestCase): @@ -64,12 +65,18 @@ self.assertTrue(path in sys.path_importer_cache) self.assertTrue(sys.path_importer_cache[path] is importer) - def test_path_importer_cache_has_None(self): - # Test that if sys.path_importer_cache has None that None is returned. - clear_cache = {path: None for path in sys.path} - with util.import_state(path_importer_cache=clear_cache): - for name in ('asynchat', 'sys', ''): - self.assertTrue(machinery.PathFinder.find_module(name) is None) + def test_empty_path_hooks(self): + # Test that if sys.path_hooks is empty a warning is raised and + # PathFinder returns None. + # tried again (with a warning). + with util.import_state(path_importer_cache={}, path_hooks=[], + path=['bogus_path']): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + self.assertIsNone(machinery.PathFinder.find_module('os')) + self.assertNotIn('os', sys.path_importer_cache) + self.assertEqual(len(w), 1) + self.assertTrue(issubclass(w[-1].category, ImportWarning)) def test_path_importer_cache_has_None_continues(self): # Test that having None in sys.path_importer_cache causes the search to @@ -78,9 +85,16 @@ module = '' importer = util.mock_modules(module) with util.import_state(path=['1', '2'], - path_importer_cache={'1': None, '2': importer}): - loader = machinery.PathFinder.find_module(module) - self.assertTrue(loader is importer) + path_importer_cache={'1': None, '2': importer}, + path_hooks=[imp.NullImporter]): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + loader = machinery.PathFinder.find_module(module) + self.assertTrue(loader is importer) + self.assertEqual(len(w), 1) + warned = w[0] + self.assertTrue(issubclass(warned.category, ImportWarning)) + self.assertIn(repr(None), str(warned.message)) def test_path_importer_cache_empty_string(self): # The empty string should create a finder using the cwd. @@ -94,57 +108,9 @@ self.assertIn(os.curdir, sys.path_importer_cache) -class DefaultPathFinderTests(unittest.TestCase): - - """Test _bootstrap._DefaultPathFinder.""" - - def test_implicit_hooks(self): - # Test that the implicit path hooks are used. - bad_path = '' - module = '' - assert not os.path.exists(bad_path) - existing_path = tempfile.mkdtemp() - try: - with util.import_state(): - nothing = _bootstrap._DefaultPathFinder.find_module(module, - path=[existing_path]) - self.assertTrue(nothing is None) - self.assertTrue(existing_path in sys.path_importer_cache) - result = isinstance(sys.path_importer_cache[existing_path], - imp.NullImporter) - self.assertFalse(result) - nothing = _bootstrap._DefaultPathFinder.find_module(module, - path=[bad_path]) - self.assertTrue(nothing is None) - self.assertTrue(bad_path in sys.path_importer_cache) - self.assertTrue(isinstance(sys.path_importer_cache[bad_path], - imp.NullImporter)) - finally: - os.rmdir(existing_path) - - - def test_path_importer_cache_has_None(self): - # Test that the default hook is used when sys.path_importer_cache - # contains None for a path. - module = '' - importer = util.mock_modules(module) - path = '' - # XXX Not blackbox. - original_hook = _bootstrap._DEFAULT_PATH_HOOK - mock_hook = import_util.mock_path_hook(path, importer=importer) - _bootstrap._DEFAULT_PATH_HOOK = mock_hook - try: - with util.import_state(path_importer_cache={path: None}): - loader = _bootstrap._DefaultPathFinder.find_module(module, - path=[path]) - self.assertTrue(loader is importer) - finally: - _bootstrap._DEFAULT_PATH_HOOK = original_hook - - def test_main(): from test.support import run_unittest - run_unittest(FinderTests, DefaultPathFinderTests) + run_unittest(FinderTests) if __name__ == '__main__': test_main() diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -379,18 +379,15 @@ for path_hook in sys.path_hooks: try: importer = path_hook(path_item) + sys.path_importer_cache.setdefault(path_item, importer) break except ImportError: pass else: - importer = None - sys.path_importer_cache.setdefault(path_item, importer) - - if importer is None: - try: - importer = ImpImporter(path_item) - except ImportError: - importer = None + try: + importer = ImpImporter(path_item) + except ImportError: + importer = None return importer diff --git a/Lib/runpy.py b/Lib/runpy.py --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -9,6 +9,7 @@ # Written by Nick Coghlan # to implement PEP 338 (Executing Modules as Scripts) +import os import sys import imp from pkgutil import read_code @@ -94,7 +95,7 @@ for attr in ("get_filename", "_get_filename"): meth = getattr(loader, attr, None) if meth is not None: - return meth(mod_name) + return os.path.abspath(meth(mod_name)) return None # Helper to get the loader, code and filename for a module @@ -198,10 +199,6 @@ try: importer = cache[path_name] except KeyError: - # Not yet cached. Flag as using the - # standard machinery until we finish - # checking the hooks - cache[path_name] = None for hook in sys.path_hooks: try: importer = hook(path_name) @@ -213,10 +210,7 @@ # NullImporter throws ImportError if the supplied path is a # *valid* directory entry (and hence able to be handled # by the standard import machinery) - try: - importer = imp.NullImporter(path_name) - except ImportError: - return None + importer = imp.NullImporter(path_name) cache[path_name] = importer return importer diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -1,5 +1,6 @@ # tests command line execution of scripts +import importlib import unittest import sys import os @@ -49,12 +50,16 @@ """ def _make_test_script(script_dir, script_basename, source=test_source): - return make_script(script_dir, script_basename, source) + to_return = make_script(script_dir, script_basename, source) + importlib.invalidate_caches() + return to_return def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, source=test_source, depth=1): - return make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, - source, depth) + to_return = make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, + source, depth) + importlib.invalidate_caches() + return to_return # There's no easy way to pass the script directory in to get # -m to work (avoiding that is the whole point of making @@ -72,7 +77,9 @@ else: path = repr(path) source = launch_source % (path, module_name) - return make_script(script_dir, script_basename, source) + to_return = make_script(script_dir, script_basename, source) + importlib.invalidate_caches() + return to_return class CmdLineTest(unittest.TestCase): def _check_output(self, script_name, exit_code, data, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ Core and Builtins ----------------- +- Issue #14605: No longer have implicit entries in sys.path_hooks. If + sys.path_hooks is found to be empty, a warning will be raised. If None is + found in sys.path_importer_cache, a warning is raised and a search on + sys.path_hooks is attempted. + - Issue #13903: Implement PEP 412. Individual dictionary instances can now share their keys with other dictionaries. Classes take advantage of this to share their instance dictionary keys for improved memory and performance. diff --git a/Python/importlib.h b/Python/importlib.h index 991334e6316f63a1c5e7bd01307b045cffd9798e..7a83c0239cb1e9ca030daf74a03bfe3c6859b220 GIT binary patch [stripped] diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -229,7 +229,7 @@ Py_FatalError("Py_Initialize: can't save _imp to sys.modules"); } - value = PyObject_CallMethod(importlib, "_setup", "OO", sysmod, impmod); + value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod); if (value == NULL) { PyErr_Print(); Py_FatalError("Py_Initialize: importlib install failed"); -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Apr 26 05:40:26 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 26 Apr 2012 05:40:26 +0200 Subject: [Python-checkins] Daily reference leaks (57d558f1904d): sum=6 Message-ID: results for 57d558f1904d on branch "default" -------------------------------------------- test_tempfile leaked [2, 2, 2] references, sum=6 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogNUyUFt', '-x'] From python-checkins at python.org Thu Apr 26 06:27:16 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Apr 2012 06:27:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_only_incref_when_using_borr?= =?utf8?q?owing_functions?= Message-ID: http://hg.python.org/cpython/rev/1e44f3ee5bd3 changeset: 76567:1e44f3ee5bd3 parent: 76558:5fea362b92fc user: Benjamin Peterson date: Thu Apr 26 00:26:37 2012 -0400 summary: only incref when using borrowing functions files: Python/ceval.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2132,6 +2132,7 @@ GLOBAL_NAME_ERROR_MSG, w); break; } + Py_INCREF(x); } else { /* Slow-path if globals or builtins is not a dict */ @@ -2147,7 +2148,6 @@ } } } - Py_INCREF(x); PUSH(x); DISPATCH(); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 06:27:18 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Apr 2012 06:27:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge_heads?= Message-ID: http://hg.python.org/cpython/rev/c52caa0a8056 changeset: 76568:c52caa0a8056 parent: 76567:1e44f3ee5bd3 parent: 76566:57d558f1904d user: Benjamin Peterson date: Thu Apr 26 00:27:06 2012 -0400 summary: merge heads files: Lib/importlib/_bootstrap.py | 64 ++----- Lib/importlib/test/import_/test_fromlist.py | 4 +- Lib/importlib/test/import_/test_path.py | 82 ++------- Lib/pkgutil.py | 13 +- Lib/runpy.py | 12 +- Lib/test/test_cgi.py | 11 +- Lib/test/test_cmd_line_script.py | 15 +- Lib/test/test_importhooks.py | 4 +- Lib/test/test_threaded_import.py | 2 +- Misc/NEWS | 5 + Objects/longobject.c | 2 + Objects/unicodeobject.c | 8 +- Python/import.c | 4 +- Python/importlib.h | Bin Python/pythonrun.c | 2 +- 15 files changed, 92 insertions(+), 136 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -752,15 +752,15 @@ """Meta path finder for sys.(path|path_hooks|path_importer_cache).""" @classmethod - def _path_hooks(cls, path, hooks=None): + def _path_hooks(cls, path): """Search sequence of hooks for a finder for 'path'. If 'hooks' is false then use sys.path_hooks. """ - if hooks is None: - hooks = sys.path_hooks - for hook in hooks: + if not sys.path_hooks: + _warnings.warn('sys.path_hooks is empty', ImportWarning) + for hook in sys.path_hooks: try: return hook(path) except ImportError: @@ -770,14 +770,11 @@ path=path) @classmethod - def _path_importer_cache(cls, path, default=None): + def _path_importer_cache(cls, path): """Get the finder for the path from sys.path_importer_cache. If the path is not in the cache, find the appropriate finder and cache - it. If None is cached, get the default finder and cache that - (if applicable). - - Because of NullImporter, some finder should be returned. The only + it. Because of NullImporter, some finder should be returned. The only explicit fail case is if None is cached but the path cannot be used for the default hook, for which ImportError is raised. @@ -790,9 +787,13 @@ finder = cls._path_hooks(path) sys.path_importer_cache[path] = finder else: - if finder is None and default: - # Raises ImportError on failure. - finder = default(path) + if finder is None: + msg = ("'None' in sys.path_importer_cache[{!r}], so retrying " + "finder search; in future versions of Python 'None' " + "will represent no finder".format(path)) + _warnings.warn(msg, ImportWarning) + del sys.path_importer_cache[path] + finder = cls._path_hooks(path) sys.path_importer_cache[path] = finder return finder @@ -931,29 +932,6 @@ # Import itself ############################################################### -_DEFAULT_PATH_HOOK = None # Set in _setup() - -class _DefaultPathFinder(PathFinder): - - """Subclass of PathFinder that implements implicit semantics for - __import__.""" - - @classmethod - def _path_hooks(cls, path): - """Search sys.path_hooks as well as implicit path hooks.""" - try: - return super()._path_hooks(path) - except ImportError: - implicit_hooks = [_DEFAULT_PATH_HOOK, _imp.NullImporter] - return super()._path_hooks(path, implicit_hooks) - - @classmethod - def _path_importer_cache(cls, path): - """Use the default path hook when None is stored in - sys.path_importer_cache.""" - return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK) - - class _ImportLockContext: """Context manager for the import lock.""" @@ -1008,7 +986,7 @@ raise ValueError("Empty module name") -_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder] +_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, PathFinder] _ERR_MSG = 'No module named {!r}' @@ -1203,12 +1181,6 @@ if builtin_os == 'nt': SOURCE_SUFFIXES.append('.pyw') - supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), - (SourceFileLoader, _suffix_list(1), True), - (SourcelessFileLoader, _suffix_list(2), True)] - setattr(self_module, '_DEFAULT_PATH_HOOK', - FileFinder.path_hook(*supported_loaders)) - def _install(sys_module, _imp_module): """Install importlib as the implementation of import. @@ -1218,6 +1190,8 @@ """ _setup(sys_module, _imp_module) - orig_import = builtins.__import__ - builtins.__import__ = __import__ - builtins.__original_import__ = orig_import + supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), + (SourceFileLoader, _suffix_list(1), True), + (SourcelessFileLoader, _suffix_list(2), True)] + sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders), + _imp.NullImporter]) diff --git a/Lib/importlib/test/import_/test_fromlist.py b/Lib/importlib/test/import_/test_fromlist.py --- a/Lib/importlib/test/import_/test_fromlist.py +++ b/Lib/importlib/test/import_/test_fromlist.py @@ -1,6 +1,7 @@ """Test that the semantics relating to the 'fromlist' argument are correct.""" from .. import util from . import util as import_util +import imp import unittest class ReturnValue(unittest.TestCase): @@ -73,7 +74,8 @@ def test_no_module_from_package(self): # [no module] with util.mock_modules('pkg.__init__') as importer: - with util.import_state(meta_path=[importer]): + with util.import_state(meta_path=[importer], + path_hooks=[imp.NullImporter]): module = import_util.import_('pkg', fromlist='non_existent') self.assertEqual(module.__name__, 'pkg') self.assertTrue(not hasattr(module, 'non_existent')) diff --git a/Lib/importlib/test/import_/test_path.py b/Lib/importlib/test/import_/test_path.py --- a/Lib/importlib/test/import_/test_path.py +++ b/Lib/importlib/test/import_/test_path.py @@ -9,6 +9,7 @@ from test import support from types import MethodType import unittest +import warnings class FinderTests(unittest.TestCase): @@ -64,12 +65,18 @@ self.assertTrue(path in sys.path_importer_cache) self.assertTrue(sys.path_importer_cache[path] is importer) - def test_path_importer_cache_has_None(self): - # Test that if sys.path_importer_cache has None that None is returned. - clear_cache = {path: None for path in sys.path} - with util.import_state(path_importer_cache=clear_cache): - for name in ('asynchat', 'sys', ''): - self.assertTrue(machinery.PathFinder.find_module(name) is None) + def test_empty_path_hooks(self): + # Test that if sys.path_hooks is empty a warning is raised and + # PathFinder returns None. + # tried again (with a warning). + with util.import_state(path_importer_cache={}, path_hooks=[], + path=['bogus_path']): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + self.assertIsNone(machinery.PathFinder.find_module('os')) + self.assertNotIn('os', sys.path_importer_cache) + self.assertEqual(len(w), 1) + self.assertTrue(issubclass(w[-1].category, ImportWarning)) def test_path_importer_cache_has_None_continues(self): # Test that having None in sys.path_importer_cache causes the search to @@ -78,9 +85,16 @@ module = '' importer = util.mock_modules(module) with util.import_state(path=['1', '2'], - path_importer_cache={'1': None, '2': importer}): - loader = machinery.PathFinder.find_module(module) - self.assertTrue(loader is importer) + path_importer_cache={'1': None, '2': importer}, + path_hooks=[imp.NullImporter]): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + loader = machinery.PathFinder.find_module(module) + self.assertTrue(loader is importer) + self.assertEqual(len(w), 1) + warned = w[0] + self.assertTrue(issubclass(warned.category, ImportWarning)) + self.assertIn(repr(None), str(warned.message)) def test_path_importer_cache_empty_string(self): # The empty string should create a finder using the cwd. @@ -94,57 +108,9 @@ self.assertIn(os.curdir, sys.path_importer_cache) -class DefaultPathFinderTests(unittest.TestCase): - - """Test _bootstrap._DefaultPathFinder.""" - - def test_implicit_hooks(self): - # Test that the implicit path hooks are used. - bad_path = '' - module = '' - assert not os.path.exists(bad_path) - existing_path = tempfile.mkdtemp() - try: - with util.import_state(): - nothing = _bootstrap._DefaultPathFinder.find_module(module, - path=[existing_path]) - self.assertTrue(nothing is None) - self.assertTrue(existing_path in sys.path_importer_cache) - result = isinstance(sys.path_importer_cache[existing_path], - imp.NullImporter) - self.assertFalse(result) - nothing = _bootstrap._DefaultPathFinder.find_module(module, - path=[bad_path]) - self.assertTrue(nothing is None) - self.assertTrue(bad_path in sys.path_importer_cache) - self.assertTrue(isinstance(sys.path_importer_cache[bad_path], - imp.NullImporter)) - finally: - os.rmdir(existing_path) - - - def test_path_importer_cache_has_None(self): - # Test that the default hook is used when sys.path_importer_cache - # contains None for a path. - module = '' - importer = util.mock_modules(module) - path = '' - # XXX Not blackbox. - original_hook = _bootstrap._DEFAULT_PATH_HOOK - mock_hook = import_util.mock_path_hook(path, importer=importer) - _bootstrap._DEFAULT_PATH_HOOK = mock_hook - try: - with util.import_state(path_importer_cache={path: None}): - loader = _bootstrap._DefaultPathFinder.find_module(module, - path=[path]) - self.assertTrue(loader is importer) - finally: - _bootstrap._DEFAULT_PATH_HOOK = original_hook - - def test_main(): from test.support import run_unittest - run_unittest(FinderTests, DefaultPathFinderTests) + run_unittest(FinderTests) if __name__ == '__main__': test_main() diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -379,18 +379,15 @@ for path_hook in sys.path_hooks: try: importer = path_hook(path_item) + sys.path_importer_cache.setdefault(path_item, importer) break except ImportError: pass else: - importer = None - sys.path_importer_cache.setdefault(path_item, importer) - - if importer is None: - try: - importer = ImpImporter(path_item) - except ImportError: - importer = None + try: + importer = ImpImporter(path_item) + except ImportError: + importer = None return importer diff --git a/Lib/runpy.py b/Lib/runpy.py --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -9,6 +9,7 @@ # Written by Nick Coghlan # to implement PEP 338 (Executing Modules as Scripts) +import os import sys import imp from pkgutil import read_code @@ -94,7 +95,7 @@ for attr in ("get_filename", "_get_filename"): meth = getattr(loader, attr, None) if meth is not None: - return meth(mod_name) + return os.path.abspath(meth(mod_name)) return None # Helper to get the loader, code and filename for a module @@ -198,10 +199,6 @@ try: importer = cache[path_name] except KeyError: - # Not yet cached. Flag as using the - # standard machinery until we finish - # checking the hooks - cache[path_name] = None for hook in sys.path_hooks: try: importer = hook(path_name) @@ -213,10 +210,7 @@ # NullImporter throws ImportError if the supplied path is a # *valid* directory entry (and hence able to be handled # by the standard import machinery) - try: - importer = imp.NullImporter(path_name) - except ImportError: - return None + importer = imp.NullImporter(path_name) cache[path_name] = importer return importer 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 @@ -4,6 +4,7 @@ import sys import tempfile import unittest +import warnings from io import StringIO, BytesIO class HackedSysModule: @@ -119,9 +120,13 @@ class CgiTests(unittest.TestCase): def test_escape(self): - self.assertEqual("test & string", cgi.escape("test & string")) - self.assertEqual("<test string>", cgi.escape("")) - self.assertEqual(""test string"", cgi.escape('"test string"', True)) + # cgi.escape() is deprecated. + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', 'cgi\.escape', + DeprecationWarning) + self.assertEqual("test & string", cgi.escape("test & string")) + self.assertEqual("<test string>", cgi.escape("")) + self.assertEqual(""test string"", cgi.escape('"test string"', True)) def test_strict(self): for orig, expect in parse_strict_test_cases: diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -1,5 +1,6 @@ # tests command line execution of scripts +import importlib import unittest import sys import os @@ -49,12 +50,16 @@ """ def _make_test_script(script_dir, script_basename, source=test_source): - return make_script(script_dir, script_basename, source) + to_return = make_script(script_dir, script_basename, source) + importlib.invalidate_caches() + return to_return def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, source=test_source, depth=1): - return make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, - source, depth) + to_return = make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, + source, depth) + importlib.invalidate_caches() + return to_return # There's no easy way to pass the script directory in to get # -m to work (avoiding that is the whole point of making @@ -72,7 +77,9 @@ else: path = repr(path) source = launch_source % (path, module_name) - return make_script(script_dir, script_basename, source) + to_return = make_script(script_dir, script_basename, source) + importlib.invalidate_caches() + return to_return class CmdLineTest(unittest.TestCase): def _check_output(self, script_name, exit_code, data, diff --git a/Lib/test/test_importhooks.py b/Lib/test/test_importhooks.py --- a/Lib/test/test_importhooks.py +++ b/Lib/test/test_importhooks.py @@ -215,7 +215,7 @@ self.doTestImports(i) def testPathHook(self): - sys.path_hooks.append(PathImporter) + sys.path_hooks.insert(0, PathImporter) sys.path.append(test_path) self.doTestImports() @@ -228,7 +228,7 @@ def testImpWrapper(self): i = ImpWrapper() sys.meta_path.append(i) - sys.path_hooks.append(ImpWrapper) + sys.path_hooks.insert(0, ImpWrapper) mnames = ( "colorsys", "urllib.parse", "distutils.core", "sys", ) diff --git a/Lib/test/test_threaded_import.py b/Lib/test/test_threaded_import.py --- a/Lib/test/test_threaded_import.py +++ b/Lib/test/test_threaded_import.py @@ -145,7 +145,7 @@ def path_hook(path): finder.find_module('') raise ImportError - sys.path_hooks.append(path_hook) + sys.path_hooks.insert(0, path_hook) sys.meta_path.append(flushing_finder) try: # Flush the cache a first time diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ Core and Builtins ----------------- +- Issue #14605: No longer have implicit entries in sys.path_hooks. If + sys.path_hooks is found to be empty, a warning will be raised. If None is + found in sys.path_importer_cache, a warning is raised and a search on + sys.path_hooks is attempted. + - Issue #13903: Implement PEP 412. Individual dictionary instances can now share their keys with other dictionaries. Classes take advantage of this to share their instance dictionary keys for improved memory and performance. diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1657,6 +1657,7 @@ /* check we've counted correctly */ assert(p == PyUnicode_1BYTE_DATA(str)); + assert(_PyUnicode_CheckConsistency(str, 1)); Py_DECREF(scratch); return (PyObject *)str; } @@ -1761,6 +1762,7 @@ if (negative) *--p = '-'; assert(p == PyUnicode_1BYTE_DATA(v)); + assert(_PyUnicode_CheckConsistency(v, 1)); return v; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -375,10 +375,13 @@ { Py_ssize_t i; Py_UCS4 maxchar = 0; - void *data = PyUnicode_DATA(ascii); + void *data; + Py_UCS4 ch; + + data = PyUnicode_DATA(ascii); for (i=0; i < ascii->length; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); + ch = PyUnicode_READ(kind, data, i); if (ch > maxchar) maxchar = ch; } @@ -398,6 +401,7 @@ assert(maxchar >= 0x10000); assert(maxchar <= MAX_UNICODE); } + assert(PyUnicode_READ(kind, data, ascii->length) == 0); } return 1; } diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -268,8 +268,8 @@ "# can't import zipimport.zipimporter\n"); } else { - /* sys.path_hooks.append(zipimporter) */ - err = PyList_Append(path_hooks, zipimporter); + /* sys.path_hooks.insert(0, zipimporter) */ + err = PyList_Insert(path_hooks, 0, zipimporter); Py_DECREF(zipimporter); if (err < 0) { goto error; diff --git a/Python/importlib.h b/Python/importlib.h index 9dbd8816f3060d4ea66d3db7b1980139214e3908..7a83c0239cb1e9ca030daf74a03bfe3c6859b220 GIT binary patch [stripped] diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -229,7 +229,7 @@ Py_FatalError("Py_Initialize: can't save _imp to sys.modules"); } - value = PyObject_CallMethod(importlib, "_setup", "OO", sysmod, impmod); + value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod); if (value == NULL) { PyErr_Print(); Py_FatalError("Py_Initialize: importlib install failed"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 06:41:47 2012 From: python-checkins at python.org (brian.curtin) Date: Thu, 26 Apr 2012 06:41:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Add_a_missing_close_paren?= Message-ID: http://hg.python.org/cpython/rev/6b9c1adce91e changeset: 76569:6b9c1adce91e user: Brian Curtin date: Wed Apr 25 23:38:05 2012 -0500 summary: Add a missing close paren files: Tools/msi/msi.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py --- a/Tools/msi/msi.py +++ b/Tools/msi/msi.py @@ -859,7 +859,7 @@ htmlfiles = Feature(db, "Documentation", "Documentation", "Python HTMLHelp File", 7, parent = default_feature) tools = Feature(db, "Tools", "Utility Scripts", - "Python utility scripts (Tools/", 9, + "Python utility scripts (Tools/)", 9, parent = default_feature, attributes=2) testsuite = Feature(db, "Testsuite", "Test suite", "Python test suite (Lib/test/)", 11, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 10:57:35 2012 From: python-checkins at python.org (eric.smith) Date: Thu, 26 Apr 2012 10:57:35 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Drop_implementation_detail=2E?= Message-ID: http://hg.python.org/peps/rev/12dac1cd9b96 changeset: 4310:12dac1cd9b96 user: Eric V. Smith date: Thu Apr 26 04:57:05 2012 -0400 summary: Drop implementation detail. files: pep-0420.txt | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -159,7 +159,6 @@ the string that will be recorded and later used as a component of the namespace module's __path__, as described above. -[Consider Brett's idea to pass NamespaceLoader in to PathFinder] Discussion ========== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 26 14:30:27 2012 From: python-checkins at python.org (eric.smith) Date: Thu, 26 Apr 2012 14:30:27 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Slight_clarifications_about_pa?= =?utf8?q?ckaging=2E?= Message-ID: http://hg.python.org/peps/rev/4c08c21cfacd changeset: 4311:4c08c21cfacd user: Eric V. Smith date: Thu Apr 26 08:30:19 2012 -0400 summary: Slight clarifications about packaging. files: pep-0420.txt | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -199,9 +199,9 @@ ====================== Multiple portions of a namespace package can be installed into the -same location, or into separate locations. For this section, suppose -there are two portions which define "foo.bar" and "foo.baz". "foo" -itself is a namespace package. +same directory, or into separate directories. For this section, +suppose there are two portions which define "foo.bar" and "foo.baz". +"foo" itself is a namespace package. If these are installed in the same location, a single directory "foo" would be in a directory that is on ``sys.path``. Inside "foo" would @@ -215,7 +215,7 @@ "foo" directories would be in directories that are on ``sys.path``. "foo/bar" would be in one of these sys.path entries, and "foo/baz" would be in the other. Upon removal of "foo.bar", the "foo/bar" and -corresonding "foo" directories can be removed. +corresonding "foo" directories can be completely removed. Note that even if they are installed in the same directory, "foo.bar" and "foo.baz" would not have any files in common. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 26 16:39:46 2012 From: python-checkins at python.org (jesus.cea) Date: Thu, 26 Apr 2012 16:39:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Close_=2310142=3A_Support_f?= =?utf8?q?or_SEEK=5FHOLE/SEEK=5FDATA?= Message-ID: http://hg.python.org/cpython/rev/86dc014cdd74 changeset: 76570:86dc014cdd74 user: Jesus Cea date: Thu Apr 26 16:39:35 2012 +0200 summary: Close #10142: Support for SEEK_HOLE/SEEK_DATA files: Doc/library/io.rst | 5 +++++ Doc/library/os.rst | 4 ++++ Lib/_pyio.py | 12 +++--------- Lib/os.py | 1 + Lib/test/test_posix.py | 20 ++++++++++++++++++++ Misc/NEWS | 2 ++ Modules/_io/bufferedio.c | 21 ++++++++++++++++++--- Modules/posixmodule.c | 7 +++++++ 8 files changed, 60 insertions(+), 12 deletions(-) diff --git a/Doc/library/io.rst b/Doc/library/io.rst --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -291,6 +291,11 @@ .. versionadded:: 3.1 The ``SEEK_*`` constants. + .. versionadded:: 3.3 + Some operating systems could support additional values, like + :data:`os.SEEK_HOLE` or :data:`os.SEEK_DATA`. The valid values + for a file could depend on it being open in text or binary mode. + .. method:: seekable() Return ``True`` if the stream supports random access. If ``False``, diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -992,6 +992,10 @@ Parameters to the :func:`lseek` function. Their values are 0, 1, and 2, respectively. Availability: Windows, Unix. + .. versionadded:: 3.3 + Some operating systems could support additional values, like + :data:`os.SEEK_HOLE` or :data:`os.SEEK_DATA`. + .. function:: mkdirat(dirfd, path, mode=0o777) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -306,6 +306,7 @@ * 0 -- start of stream (the default); offset should be zero or positive * 1 -- current stream position; offset may be negative * 2 -- end of stream; offset is usually negative + Some operating systems / file systems could provide additional values. Return an int indicating the new absolute position. """ @@ -866,7 +867,7 @@ elif whence == 2: self._pos = max(0, len(self._buffer) + pos) else: - raise ValueError("invalid whence value") + raise ValueError("unsupported whence value") return self._pos def tell(self): @@ -1041,8 +1042,6 @@ return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos def seek(self, pos, whence=0): - if not (0 <= whence <= 2): - raise ValueError("invalid whence value") with self._read_lock: if whence == 1: pos -= len(self._read_buf) - self._read_pos @@ -1138,8 +1137,6 @@ return _BufferedIOMixin.tell(self) + len(self._write_buf) def seek(self, pos, whence=0): - if not (0 <= whence <= 2): - raise ValueError("invalid whence") with self._write_lock: self._flush_unlocked() return _BufferedIOMixin.seek(self, pos, whence) @@ -1235,8 +1232,6 @@ BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) def seek(self, pos, whence=0): - if not (0 <= whence <= 2): - raise ValueError("invalid whence") self.flush() if self._read_buf: # Undo read ahead. @@ -1852,8 +1847,7 @@ self._decoder.reset() return position if whence != 0: - raise ValueError("invalid whence (%r, should be 0, 1 or 2)" % - (whence,)) + raise ValueError("unsupported whence (%r)" % (whence,)) if cookie < 0: raise ValueError("negative seek position %r" % (cookie,)) self.flush() diff --git a/Lib/os.py b/Lib/os.py --- a/Lib/os.py +++ b/Lib/os.py @@ -116,6 +116,7 @@ # Python uses fixed values for the SEEK_ constants; they are mapped # to native constants if necessary in posixmodule.c +# Other possible SEEK values are directly imported from posixmodule.c SEEK_SET = 0 SEEK_CUR = 1 SEEK_END = 2 diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1009,6 +1009,26 @@ posix.RTLD_GLOBAL posix.RTLD_LOCAL + @unittest.skipUnless('PC_MIN_HOLE_SIZE' in os.pathconf_names, + "test needs an OS that reports file holes") + def test_fs_holes(self) : + # Even if the filesystem doesn't report holes, + # if the OS supports it the SEEK_* constants + # will be defined and will have a consistent + # behaviour: + # os.SEEK_DATA = current position + # os.SEEK_HOLE = end of file position + with open(support.TESTFN, 'r+b') as fp : + fp.write(b"hello") + fp.flush() + size = fp.tell() + fno = fp.fileno() + for i in range(size) : + self.assertEqual(i, os.lseek(fno, i, os.SEEK_DATA)) + self.assertLessEqual(size, os.lseek(fno, i, os.SEEK_HOLE)) + self.assertRaises(OSError, os.lseek, fno, size, os.SEEK_DATA) + self.assertRaises(OSError, os.lseek, fno, size, os.SEEK_HOLE) + class PosixGroupsTester(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -423,6 +423,8 @@ - Issue #14259: The finditer() method of re objects did not take any keyword arguments, contrary to the documentation. +- Issue #10142: Support for SEEK_HOLE/SEEK_DATA (for example, under ZFS). + Tests ----- diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1157,9 +1157,20 @@ if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) { return NULL; } - if (whence < 0 || whence > 2) { + + /* Do some error checking instead of trusting OS 'seek()' + ** error detection, just in case. + */ + if ((whence < 0 || whence >2) +#ifdef SEEK_HOLE + && (whence != SEEK_HOLE) +#endif +#ifdef SEEK_DATA + && (whence != SEEK_DATA) +#endif + ) { PyErr_Format(PyExc_ValueError, - "whence must be between 0 and 2, not %d", whence); + "whence value %d unsupported", whence); return NULL; } @@ -1172,7 +1183,11 @@ if (target == -1 && PyErr_Occurred()) return NULL; - if (whence != 2 && self->readable) { + /* SEEK_SET and SEEK_CUR are special because we could seek inside the + buffer. Other whence values must be managed without this optimization. + Some Operating Systems can provide additional values, like + SEEK_HOLE/SEEK_DATA. */ + if (((whence == 0) || (whence == 1)) && self->readable) { Py_off_t current, avail; /* Check if seeking leaves us inside the current buffer, so as to return quickly if possible. Also, we needn't take the diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11227,6 +11227,13 @@ #endif +#ifdef SEEK_HOLE + if (ins(d, "SEEK_HOLE", (long)SEEK_HOLE)) return -1; +#endif +#ifdef SEEK_DATA + if (ins(d, "SEEK_DATA", (long)SEEK_DATA)) return -1; +#endif + /* MS Windows */ #ifdef O_NOINHERIT /* Don't inherit in child processes. */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 17:05:45 2012 From: python-checkins at python.org (jesus.cea) Date: Thu, 26 Apr 2012 17:05:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Backing_out_86dc014cdd74=2E?= =?utf8?q?_Not_ready_yet?= Message-ID: http://hg.python.org/cpython/rev/2f563908ebc5 changeset: 76571:2f563908ebc5 user: Jesus Cea date: Thu Apr 26 17:05:31 2012 +0200 summary: Backing out 86dc014cdd74. Not ready yet files: Doc/library/io.rst | 5 ----- Doc/library/os.rst | 4 ---- Lib/_pyio.py | 12 +++++++++--- Lib/os.py | 1 - Lib/test/test_posix.py | 20 -------------------- Misc/NEWS | 2 -- Modules/_io/bufferedio.c | 21 +++------------------ Modules/posixmodule.c | 7 ------- 8 files changed, 12 insertions(+), 60 deletions(-) diff --git a/Doc/library/io.rst b/Doc/library/io.rst --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -291,11 +291,6 @@ .. versionadded:: 3.1 The ``SEEK_*`` constants. - .. versionadded:: 3.3 - Some operating systems could support additional values, like - :data:`os.SEEK_HOLE` or :data:`os.SEEK_DATA`. The valid values - for a file could depend on it being open in text or binary mode. - .. method:: seekable() Return ``True`` if the stream supports random access. If ``False``, diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -992,10 +992,6 @@ Parameters to the :func:`lseek` function. Their values are 0, 1, and 2, respectively. Availability: Windows, Unix. - .. versionadded:: 3.3 - Some operating systems could support additional values, like - :data:`os.SEEK_HOLE` or :data:`os.SEEK_DATA`. - .. function:: mkdirat(dirfd, path, mode=0o777) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -306,7 +306,6 @@ * 0 -- start of stream (the default); offset should be zero or positive * 1 -- current stream position; offset may be negative * 2 -- end of stream; offset is usually negative - Some operating systems / file systems could provide additional values. Return an int indicating the new absolute position. """ @@ -867,7 +866,7 @@ elif whence == 2: self._pos = max(0, len(self._buffer) + pos) else: - raise ValueError("unsupported whence value") + raise ValueError("invalid whence value") return self._pos def tell(self): @@ -1042,6 +1041,8 @@ return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence value") with self._read_lock: if whence == 1: pos -= len(self._read_buf) - self._read_pos @@ -1137,6 +1138,8 @@ return _BufferedIOMixin.tell(self) + len(self._write_buf) def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence") with self._write_lock: self._flush_unlocked() return _BufferedIOMixin.seek(self, pos, whence) @@ -1232,6 +1235,8 @@ BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence") self.flush() if self._read_buf: # Undo read ahead. @@ -1847,7 +1852,8 @@ self._decoder.reset() return position if whence != 0: - raise ValueError("unsupported whence (%r)" % (whence,)) + raise ValueError("invalid whence (%r, should be 0, 1 or 2)" % + (whence,)) if cookie < 0: raise ValueError("negative seek position %r" % (cookie,)) self.flush() diff --git a/Lib/os.py b/Lib/os.py --- a/Lib/os.py +++ b/Lib/os.py @@ -116,7 +116,6 @@ # Python uses fixed values for the SEEK_ constants; they are mapped # to native constants if necessary in posixmodule.c -# Other possible SEEK values are directly imported from posixmodule.c SEEK_SET = 0 SEEK_CUR = 1 SEEK_END = 2 diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1009,26 +1009,6 @@ posix.RTLD_GLOBAL posix.RTLD_LOCAL - @unittest.skipUnless('PC_MIN_HOLE_SIZE' in os.pathconf_names, - "test needs an OS that reports file holes") - def test_fs_holes(self) : - # Even if the filesystem doesn't report holes, - # if the OS supports it the SEEK_* constants - # will be defined and will have a consistent - # behaviour: - # os.SEEK_DATA = current position - # os.SEEK_HOLE = end of file position - with open(support.TESTFN, 'r+b') as fp : - fp.write(b"hello") - fp.flush() - size = fp.tell() - fno = fp.fileno() - for i in range(size) : - self.assertEqual(i, os.lseek(fno, i, os.SEEK_DATA)) - self.assertLessEqual(size, os.lseek(fno, i, os.SEEK_HOLE)) - self.assertRaises(OSError, os.lseek, fno, size, os.SEEK_DATA) - self.assertRaises(OSError, os.lseek, fno, size, os.SEEK_HOLE) - class PosixGroupsTester(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -423,8 +423,6 @@ - Issue #14259: The finditer() method of re objects did not take any keyword arguments, contrary to the documentation. -- Issue #10142: Support for SEEK_HOLE/SEEK_DATA (for example, under ZFS). - Tests ----- diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1157,20 +1157,9 @@ if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) { return NULL; } - - /* Do some error checking instead of trusting OS 'seek()' - ** error detection, just in case. - */ - if ((whence < 0 || whence >2) -#ifdef SEEK_HOLE - && (whence != SEEK_HOLE) -#endif -#ifdef SEEK_DATA - && (whence != SEEK_DATA) -#endif - ) { + if (whence < 0 || whence > 2) { PyErr_Format(PyExc_ValueError, - "whence value %d unsupported", whence); + "whence must be between 0 and 2, not %d", whence); return NULL; } @@ -1183,11 +1172,7 @@ if (target == -1 && PyErr_Occurred()) return NULL; - /* SEEK_SET and SEEK_CUR are special because we could seek inside the - buffer. Other whence values must be managed without this optimization. - Some Operating Systems can provide additional values, like - SEEK_HOLE/SEEK_DATA. */ - if (((whence == 0) || (whence == 1)) && self->readable) { + if (whence != 2 && self->readable) { Py_off_t current, avail; /* Check if seeking leaves us inside the current buffer, so as to return quickly if possible. Also, we needn't take the diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11227,13 +11227,6 @@ #endif -#ifdef SEEK_HOLE - if (ins(d, "SEEK_HOLE", (long)SEEK_HOLE)) return -1; -#endif -#ifdef SEEK_DATA - if (ins(d, "SEEK_DATA", (long)SEEK_DATA)) return -1; -#endif - /* MS Windows */ #ifdef O_NOINHERIT /* Don't inherit in child processes. */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Apr 26 17:05:47 2012 From: python-checkins at python.org (eric.smith) Date: Thu, 26 Apr 2012 17:05:47 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Fixed_ImportWarning_discussion?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/peps/rev/f2a751e88bef changeset: 4312:f2a751e88bef user: Eric V. Smith date: Thu Apr 26 11:05:41 2012 -0400 summary: Fixed ImportWarning discussion. files: pep-0420.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -173,7 +173,7 @@ Note that an ImportWarning will no longer be raised for a directory lacking an ``__init__.py`` file. Such a directory will now be imported as a namespace package, whereas in prior Python versions an -ImportError would be raised. +ImportWarning would be raised. At PyCon 2012, we had a discussion about namespace packages at which PEP 382 and PEP 402 were rejected, to be replaced by this PEP [2]_. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Apr 26 23:35:53 2012 From: python-checkins at python.org (victor.stinner) Date: Thu, 26 Apr 2012 23:35:53 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Explain_why_Linux_a?= =?utf8?q?lways_announces_a_resolution_of_1_nanosecond=2C?= Message-ID: http://hg.python.org/peps/rev/143c015f85e5 changeset: 4313:143c015f85e5 user: Victor Stinner date: Thu Apr 26 23:35:48 2012 +0200 summary: PEP 418: Explain why Linux always announces a resolution of 1 nanosecond, even if the hardware has a lower resolution files: pep-0418.txt | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -772,6 +772,12 @@ architectures. They are at least provided on x86/x86_64, ARM and PowerPC. +clock_getres() returns 1 nanosecond for ``CLOCK_REALTIME`` and +``CLOCK_MONOTONIC`` regardless of underlying clock source. Read `Re: +clock_getres() and real resolution +`_ from Thomas Gleixner (9 Feb +2012) for an explanation. + The ``/sys/devices/system/clocksource/clocksource0`` directory contains two useful files: -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Fri Apr 27 05:42:01 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 27 Apr 2012 05:42:01 +0200 Subject: [Python-checkins] Daily reference leaks (2f563908ebc5): sum=0 Message-ID: results for 2f563908ebc5 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogAHYykr', '-x'] From python-checkins at python.org Fri Apr 27 09:20:51 2012 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 27 Apr 2012 09:20:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Improve_docstri?= =?utf8?q?ng?= Message-ID: http://hg.python.org/cpython/rev/097b72d73594 changeset: 76572:097b72d73594 branch: 2.7 parent: 76559:4b101df1e9f7 user: Raymond Hettinger date: Fri Apr 27 00:20:39 2012 -0700 summary: Improve docstring files: Modules/_bisectmodule.c | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -59,7 +59,8 @@ } PyDoc_STRVAR(bisect_right_doc, -"bisect_right(a, x[, lo[, hi]]) -> index\n\ +"bisect(a, x[, lo[, hi]]) -> index\n\ +bisect_right(a, x[, lo[, hi]]) -> index\n\ \n\ Return the index where to insert item x in list a, assuming a is sorted.\n\ \n\ @@ -100,7 +101,8 @@ } PyDoc_STRVAR(insort_right_doc, -"insort_right(a, x[, lo[, hi]])\n\ +"insort(a, x[, lo[, hi]])\n\ +insort_right(a, x[, lo[, hi]])\n\ \n\ Insert item x in list a, and keep it sorted assuming a is sorted.\n\ \n\ @@ -213,18 +215,15 @@ Optional args lo (default 0) and hi (default len(a)) bound the\n\ slice of a to be searched.\n"); -PyDoc_STRVAR(bisect_doc, "Alias for bisect_right().\n"); -PyDoc_STRVAR(insort_doc, "Alias for insort_right().\n"); - static PyMethodDef bisect_methods[] = { {"bisect_right", (PyCFunction)bisect_right, METH_VARARGS|METH_KEYWORDS, bisect_right_doc}, {"bisect", (PyCFunction)bisect_right, - METH_VARARGS|METH_KEYWORDS, bisect_doc}, + METH_VARARGS|METH_KEYWORDS, bisect_right_doc}, {"insort_right", (PyCFunction)insort_right, METH_VARARGS|METH_KEYWORDS, insort_right_doc}, {"insort", (PyCFunction)insort_right, - METH_VARARGS|METH_KEYWORDS, insort_doc}, + METH_VARARGS|METH_KEYWORDS, insort_right_doc}, {"bisect_left", (PyCFunction)bisect_left, METH_VARARGS|METH_KEYWORDS, bisect_left_doc}, {"insort_left", (PyCFunction)insort_left, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 13:59:45 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 27 Apr 2012 13:59:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Check_newly_created_consist?= =?utf8?q?ency_using_=5FPyUnicode=5FCheckConsistency=28str=2C_1=29?= Message-ID: http://hg.python.org/cpython/rev/1439e2d1f490 changeset: 76573:1439e2d1f490 parent: 76571:2f563908ebc5 user: Victor Stinner date: Fri Apr 27 13:55:39 2012 +0200 summary: Check newly created consistency using _PyUnicode_CheckConsistency(str, 1) * In debug mode, fill the string data with invalid characters * Simplify also reference counting in PyCodec_BackslashReplaceErrors() and PyCodec_XMLCharRefReplaceError() files: Modules/_json.c | 1 + Modules/md5module.c | 1 + Modules/sha1module.c | 1 + Modules/sha256module.c | 1 + Modules/sha512module.c | 1 + Objects/bytesobject.c | 1 + Objects/unicodeobject.c | 27 +++++++++++++++++---------- Python/codecs.c | 10 ++++++---- Python/compile.c | 1 + Python/import.c | 1 + 10 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -246,6 +246,7 @@ } } output[chars++] = '"'; + assert(_PyUnicode_CheckConsistency(rval, 1)); return rval; } diff --git a/Modules/md5module.c b/Modules/md5module.c --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -397,6 +397,7 @@ c = (digest[i] & 0xf); hex_digest[j++] = Py_hexdigits[c]; } + assert(_PyUnicode_CheckConsistency(retval, 1)); return retval; } diff --git a/Modules/sha1module.c b/Modules/sha1module.c --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -373,6 +373,7 @@ c = (digest[i] & 0xf); hex_digest[j++] = Py_hexdigits[c]; } + assert(_PyUnicode_CheckConsistency(retval, 1)); return retval; } diff --git a/Modules/sha256module.c b/Modules/sha256module.c --- a/Modules/sha256module.c +++ b/Modules/sha256module.c @@ -466,6 +466,7 @@ c = (digest[i] & 0xf); hex_digest[j++] = Py_hexdigits[c]; } + assert(_PyUnicode_CheckConsistency(retval, 1)); return retval; } diff --git a/Modules/sha512module.c b/Modules/sha512module.c --- a/Modules/sha512module.c +++ b/Modules/sha512module.c @@ -532,6 +532,7 @@ c = (digest[i] & 0xf); hex_digest[j++] = Py_hexdigits[c]; } + assert(_PyUnicode_CheckConsistency(retval, 1)); return retval; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -626,6 +626,7 @@ *p++ = c; } *p++ = quote; + assert(_PyUnicode_CheckConsistency(v, 1)); return v; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -967,7 +967,7 @@ PyObject *obj; PyCompactUnicodeObject *unicode; void *data; - int kind_state; + enum PyUnicode_Kind kind; int is_sharing, is_ascii; Py_ssize_t char_size; Py_ssize_t struct_size; @@ -986,17 +986,17 @@ is_sharing = 0; struct_size = sizeof(PyCompactUnicodeObject); if (maxchar < 128) { - kind_state = PyUnicode_1BYTE_KIND; + kind = PyUnicode_1BYTE_KIND; char_size = 1; is_ascii = 1; struct_size = sizeof(PyASCIIObject); } else if (maxchar < 256) { - kind_state = PyUnicode_1BYTE_KIND; + kind = PyUnicode_1BYTE_KIND; char_size = 1; } else if (maxchar < 65536) { - kind_state = PyUnicode_2BYTE_KIND; + kind = PyUnicode_2BYTE_KIND; char_size = 2; if (sizeof(wchar_t) == 2) is_sharing = 1; @@ -1007,7 +1007,7 @@ "invalid maximum character passed to PyUnicode_New"); return NULL; } - kind_state = PyUnicode_4BYTE_KIND; + kind = PyUnicode_4BYTE_KIND; char_size = 4; if (sizeof(wchar_t) == 4) is_sharing = 1; @@ -1041,7 +1041,7 @@ _PyUnicode_LENGTH(unicode) = size; _PyUnicode_HASH(unicode) = -1; _PyUnicode_STATE(unicode).interned = 0; - _PyUnicode_STATE(unicode).kind = kind_state; + _PyUnicode_STATE(unicode).kind = kind; _PyUnicode_STATE(unicode).compact = 1; _PyUnicode_STATE(unicode).ready = 1; _PyUnicode_STATE(unicode).ascii = is_ascii; @@ -1049,19 +1049,19 @@ ((char*)data)[size] = 0; _PyUnicode_WSTR(unicode) = NULL; } - else if (kind_state == PyUnicode_1BYTE_KIND) { + else if (kind == PyUnicode_1BYTE_KIND) { ((char*)data)[size] = 0; _PyUnicode_WSTR(unicode) = NULL; _PyUnicode_WSTR_LENGTH(unicode) = 0; unicode->utf8 = NULL; unicode->utf8_length = 0; - } + } else { unicode->utf8 = NULL; unicode->utf8_length = 0; - if (kind_state == PyUnicode_2BYTE_KIND) + if (kind == PyUnicode_2BYTE_KIND) ((Py_UCS2*)data)[size] = 0; - else /* kind_state == PyUnicode_4BYTE_KIND */ + else /* kind == PyUnicode_4BYTE_KIND */ ((Py_UCS4*)data)[size] = 0; if (is_sharing) { _PyUnicode_WSTR_LENGTH(unicode) = size; @@ -1072,6 +1072,13 @@ _PyUnicode_WSTR(unicode) = NULL; } } +#ifdef Py_DEBUG + /* Fill the data with invalid characters to detect bugs earlier. + _PyUnicode_CheckConsistency(str, 1) detects invalid characters, + at least for ASCII and UCS-4 strings. U+00FF is invalid in ASCII + and U+FFFFFFFF is an invalid character in Unicode 6.0. */ + memset(data, 0xff, size * kind); +#endif assert(_PyUnicode_CheckConsistency((PyObject*)unicode, 0)); return obj; } diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -534,6 +534,7 @@ data = PyUnicode_DATA(res); for (i = 0; i < len; ++i) PyUnicode_WRITE(kind, data, i, '?'); + assert(_PyUnicode_CheckConsistency(res, 1)); return Py_BuildValue("(Nn)", res, end); } else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { @@ -559,6 +560,7 @@ data = PyUnicode_DATA(res); for (i=0; i < len; i++) PyUnicode_WRITE(kind, data, i, Py_UNICODE_REPLACEMENT_CHARACTER); + assert(_PyUnicode_CheckConsistency(res, 1)); return Py_BuildValue("(Nn)", res, end); } else { @@ -652,8 +654,8 @@ } *outp++ = ';'; } - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); + assert(_PyUnicode_CheckConsistency(res, 1)); + restuple = Py_BuildValue("(Nn)", res, end); Py_DECREF(object); return restuple; } @@ -720,8 +722,8 @@ *outp++ = Py_hexdigits[c&0xf]; } - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); + assert(_PyUnicode_CheckConsistency(res, 1)); + restuple = Py_BuildValue("(Nn)", res, end); Py_DECREF(object); return restuple; } diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -263,6 +263,7 @@ Py_DECREF(result); return NULL; } + assert(_PyUnicode_CheckConsistency(result, 1)); return result; } diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -992,6 +992,7 @@ (j = dot0-right)); PyUnicode_WRITE(kind, data, i+j, 'p'); PyUnicode_WRITE(kind, data, i+j+1, 'y'); + assert(_PyUnicode_CheckConsistency(result, 1)); return result; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 15:04:30 2012 From: python-checkins at python.org (eric.smith) Date: Fri, 27 Apr 2012 15:04:30 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Added_mention_of_dynamic_=5F?= =?utf8?b?X3BhdGhfXyB1cGRhdGluZy4=?= Message-ID: http://hg.python.org/peps/rev/d962b34ffb84 changeset: 4314:d962b34ffb84 user: Eric V. Smith date: Fri Apr 27 09:03:59 2012 -0400 summary: Added mention of dynamic __path__ updating. files: pep-0420.txt | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -194,6 +194,11 @@ (These need to be addressed here.) +Phillip Eby asked about auto-updating of ``__path__``, instead of it +being a simple list [4]_. It is the intent of this PEP to get the +simplest possible solution working. It will be possible at a later +date to add such features. Several possible ways to do so were +discussed in the referenced email thread. Packaging Implications ====================== @@ -231,6 +236,9 @@ .. [3] Nick Coglan's objection to the lack of marker files or directories (http://mail.python.org/pipermail/import-sig/2012-March/000423.html) +.. [4] Phillip Eby's question about auto-updating __path__ + (http://mail.python.org/pipermail/import-sig/2012-April/000468.html) + Copyright ========= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 27 16:10:18 2012 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 27 Apr 2012 16:10:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314642=3A_Add_=22hg?= =?utf8?q?_touch=22_extension=2C_and_=22make_touch=22_target=2E?= Message-ID: http://hg.python.org/cpython/rev/b3d3f3238c13 changeset: 76574:b3d3f3238c13 user: Martin v. Loewis date: Fri Apr 27 16:10:21 2012 +0200 summary: Issue #14642: Add "hg touch" extension, and "make touch" target. files: .hgtouch | 12 ++++ Makefile.pre.in | 6 +- Misc/NEWS | 6 ++ Tools/hg/hgtouch.py | 99 +++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletions(-) diff --git a/.hgtouch b/.hgtouch new file mode 100644 --- /dev/null +++ b/.hgtouch @@ -0,0 +1,12 @@ +# -*- Makefile -*- +# Define dependencies of generated files that are checked into hg. +# The syntax of this file uses make rule dependencies, without actions + +Python/importlib.h: Lib/importlib/_bootstrap.py Python/freeze_importlib.py + +Include/ast.h: Parser/Python.asdl Parser/asdl.py Parser/asdl_c.py +Python/Python-ast.c: Include/ast.h + +Python/opcode_targets.h: Python/makeopcodetargets.py Lib/opcode.py + +Objects/typeslots.inc: Include/typeslots.h Objects/typeslots.py \ No newline at end of file diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1337,6 +1337,10 @@ etags Include/*.h; \ for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done +# Touch generated files +touch: + hg --config extensions.touch=Tools/hg/hgtouch.py touch -v + # Sanitation targets -- clean leaves libraries, executables and tags # files, which clobber removes as well pycremoval: @@ -1445,7 +1449,7 @@ .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure .PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools .PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean -.PHONY: smelly funny patchcheck +.PHONY: smelly funny patchcheck touch .PHONY: gdbhooks # IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -176,6 +176,12 @@ - Issue #14493: Use gvfs-open or xdg-open in webbrowser. +Build +----- + +- "make touch" will now touch generated files that are checked into Mercurial, + after a "hg update" which failed to bring the timestamps into the right order. + Tests ----- diff --git a/Tools/hg/hgtouch.py b/Tools/hg/hgtouch.py new file mode 100644 --- /dev/null +++ b/Tools/hg/hgtouch.py @@ -0,0 +1,99 @@ +"""Bring time stamps of generated checked-in files into the right order + +A versioned configuration file .hgtouch specifies generated files, in the +syntax of make rules. + + output: input1 input2 + +In addition to the dependency syntax, #-comments are supported. +""" +import os + +def parse_config(repo): + configfile = repo.wjoin(".hgtouch") + if not os.path.exists(configfile): + return {} + result = {} + with open(configfile) as f: + for line in f: + # strip comments + line = line.split('#')[0].strip() + if ':' not in line: + continue + outputs, inputs = line.split(':', 1) + outputs = outputs.split() + inputs = inputs.split() + for o in outputs: + try: + result[o].extend(inputs) + except KeyError: + result[o] = inputs + return result + +def check_rule(ui, repo, modified, output, inputs): + f_output = repo.wjoin(output) + try: + o_time = os.stat(f_output).st_mtime + except OSError: + ui.warn("Generated file %s does not exist\n" % output) + return False + need_touch = False + backdate = None + backdate_source = None + for i in inputs: + f_i = repo.wjoin(i) + try: + i_time = os.stat(f_i).st_mtime + except OSError: + ui.warn(".hgtouch input file %s does not exist\n" % i) + return False + if i in modified: + # input is modified. Need to backdate at least to i_time + if backdate is None or backdate > i_time: + backdate = i_time + backdate_source = i + continue + if o_time <= i_time: + # generated file is older, touch + need_touch = True + if backdate is not None: + ui.warn("Input %s for file %s locally modified\n" % (backdate_source, output)) + # set to 1s before oldest modified input + backdate -= 1 + os.utime(f_output, (backdate, backdate)) + return False + if need_touch: + ui.note("Touching %s\n" % output) + os.utime(f_output, None) + return True + +def do_touch(ui, repo): + modified = repo.status()[0] + dependencies = parse_config(repo) + success = True + # try processing all rules in topological order + hold_back = {} + while dependencies: + output, inputs = dependencies.popitem() + # check whether any of the inputs is generated + for i in inputs: + if i in dependencies: + hold_back[output] = inputs + continue + success = check_rule(ui, repo, modified, output, inputs) + # put back held back rules + dependencies.update(hold_back) + hold_back = {} + if hold_back: + ui.warn("Cyclic dependency involving %s\n" % (' '.join(hold_back.keys()))) + return False + return success + +def touch(ui, repo): + "touch generated files that are older than their sources after an update." + do_touch(ui, repo) + +cmdtable = { + "touch": (touch, [], + "touch generated files according to the .hgtouch configuration") +} -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 17:56:34 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 27 Apr 2012 17:56:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_use_wfile_api?= Message-ID: http://hg.python.org/cpython/rev/1c8a79c4c73e changeset: 76575:1c8a79c4c73e user: Benjamin Peterson date: Fri Apr 27 11:56:30 2012 -0400 summary: use wfile api files: Tools/hg/hgtouch.py | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Tools/hg/hgtouch.py b/Tools/hg/hgtouch.py --- a/Tools/hg/hgtouch.py +++ b/Tools/hg/hgtouch.py @@ -7,15 +7,19 @@ In addition to the dependency syntax, #-comments are supported. """ +import errno import os def parse_config(repo): - configfile = repo.wjoin(".hgtouch") - if not os.path.exists(configfile): + try: + fp = repo.wfile(".hgtouch") + except IOError, e: + if e.errno != errno.ENOENT: + raise return {} result = {} - with open(configfile) as f: - for line in f: + with fp: + for line in fp: # strip comments line = line.split('#')[0].strip() if ':' not in line: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 18:57:46 2012 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 27 Apr 2012 18:57:46 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Make_the_exampl?= =?utf8?q?e_cut_and_pasteable=2E?= Message-ID: http://hg.python.org/cpython/rev/3bac1e1a0e0d changeset: 76576:3bac1e1a0e0d branch: 2.7 parent: 76572:097b72d73594 user: Raymond Hettinger date: Fri Apr 27 09:55:31 2012 -0700 summary: Make the example cut and pasteable. files: Doc/library/bisect.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/bisect.rst b/Doc/library/bisect.rst --- a/Doc/library/bisect.rst +++ b/Doc/library/bisect.rst @@ -123,9 +123,9 @@ a 'B', and so on:: >>> def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'): - ... i = bisect(breakpoints, score) - ... return grades[i] - ... + i = bisect(breakpoints, score) + return grades[i] + >>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A'] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 20:02:41 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 20:02:41 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Invalidate_finder_caches_af?= =?utf8?q?ter_creating_a_new_script=2E?= Message-ID: http://hg.python.org/cpython/rev/4182c0e6a389 changeset: 76577:4182c0e6a389 parent: 76574:b3d3f3238c13 user: Brett Cannon date: Fri Apr 27 13:52:03 2012 -0400 summary: Invalidate finder caches after creating a new script. files: Lib/test/script_helper.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/test/script_helper.py b/Lib/test/script_helper.py --- a/Lib/test/script_helper.py +++ b/Lib/test/script_helper.py @@ -1,6 +1,7 @@ # Common utility functions used by various script execution tests # e.g. test_cmd_line, test_cmd_line_script and test_runpy +import importlib import sys import os import os.path @@ -93,6 +94,7 @@ script_file = open(script_name, 'w', encoding='utf-8') script_file.write(source) script_file.close() + importlib.invalidate_caches() return script_name def make_zip_script(zip_dir, zip_basename, script_name, name_in_zip=None): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 20:02:42 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 20:02:42 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Insert_to?= =?utf8?q?_the_front_of_sys=2Emeta=5Fpath=2C_don=27t_append=2E?= Message-ID: http://hg.python.org/cpython/rev/c18256de00bb changeset: 76578:c18256de00bb user: Brett Cannon date: Fri Apr 27 13:52:55 2012 -0400 summary: Issue #14605: Insert to the front of sys.meta_path, don't append. files: Lib/test/test_threaded_import.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_threaded_import.py b/Lib/test/test_threaded_import.py --- a/Lib/test/test_threaded_import.py +++ b/Lib/test/test_threaded_import.py @@ -126,7 +126,7 @@ def test_parallel_meta_path(self): finder = Finder() - sys.meta_path.append(finder) + sys.meta_path.insert(0, finder) try: self.check_parallel_module_init() self.assertGreater(finder.numcalls, 0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 20:02:45 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 20:02:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Stop_havi?= =?utf8?q?ng_implicit_entries_for_sys=2Emeta=5Fpath=2E?= Message-ID: http://hg.python.org/cpython/rev/3bd60cc27664 changeset: 76579:3bd60cc27664 user: Brett Cannon date: Fri Apr 27 14:01:58 2012 -0400 summary: Issue #14605: Stop having implicit entries for sys.meta_path. ImportWarning is raised if sys.meta_path is found to be empty. files: Lib/importlib/_bootstrap.py | 8 ++-- Lib/importlib/test/import_/test_meta_path.py | 18 ++++++++++ Misc/NEWS | 3 + Modules/config.c.in | 1 - PC/config.c | 1 - PC/os2emx/config.c | 1 - PC/os2vacpp/config.c | 1 - Python/importlib.h | Bin 8 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -956,8 +956,9 @@ def _find_module(name, path): """Find a module's loader.""" - meta_path = sys.meta_path + _IMPLICIT_META_PATH - for finder in meta_path: + if not sys.meta_path: + _warnings.warn('sys.meta_path is empty', ImportWarning) + for finder in sys.meta_path: loader = finder.find_module(name, path) if loader is not None: # The parent import may have already imported this module. @@ -986,8 +987,6 @@ raise ValueError("Empty module name") -_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, PathFinder] - _ERR_MSG = 'No module named {!r}' def _find_and_load(name, import_): @@ -1195,3 +1194,4 @@ (SourcelessFileLoader, _suffix_list(2), True)] sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders), _imp.NullImporter]) + sys.meta_path.extend([BuiltinImporter, FrozenImporter, PathFinder]) diff --git a/Lib/importlib/test/import_/test_meta_path.py b/Lib/importlib/test/import_/test_meta_path.py --- a/Lib/importlib/test/import_/test_meta_path.py +++ b/Lib/importlib/test/import_/test_meta_path.py @@ -1,7 +1,10 @@ from .. import util from . import util as import_util +import importlib._bootstrap +import sys from types import MethodType import unittest +import warnings class CallingOrder(unittest.TestCase): @@ -33,6 +36,21 @@ with util.import_state(meta_path=[first, second]): self.assertEqual(import_util.import_(mod_name), 42) + def test_empty(self): + # Raise an ImportWarning if sys.meta_path is empty. + module_name = 'nothing' + try: + del sys.modules[module_name] + except KeyError: + pass + with util.import_state(meta_path=[]): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + self.assertIsNone(importlib._bootstrap._find_module('nothing', + None)) + self.assertEqual(len(w), 1) + self.assertTrue(issubclass(w[-1].category, ImportWarning)) + class CallSignature(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14605: No longer have implicit entries in sys.meta_path. If + sys.meta_path is found to be empty, raise ImportWarning. + - Issue #14605: No longer have implicit entries in sys.path_hooks. If sys.path_hooks is found to be empty, a warning will be raised. If None is found in sys.path_importer_cache, a warning is raised and a search on diff --git a/Modules/config.c.in b/Modules/config.c.in --- a/Modules/config.c.in +++ b/Modules/config.c.in @@ -45,7 +45,6 @@ {"_ast", PyInit__ast}, /* These entries are here for sys.builtin_module_names */ - {"__main__", NULL}, {"builtins", NULL}, {"sys", NULL}, diff --git a/PC/config.c b/PC/config.c --- a/PC/config.c +++ b/PC/config.c @@ -146,7 +146,6 @@ {"_imp", PyInit_imp}, /* These entries are here for sys.builtin_module_names */ - {"__main__", NULL}, {"builtins", NULL}, {"sys", NULL}, {"_warnings", _PyWarnings_Init}, diff --git a/PC/os2emx/config.c b/PC/os2emx/config.c --- a/PC/os2emx/config.c +++ b/PC/os2emx/config.c @@ -153,7 +153,6 @@ {"_imp", initimp}, /* These entries are here for sys.builtin_module_names */ - {"__main__", NULL}, {"builtins", NULL}, {"sys", NULL}, diff --git a/PC/os2vacpp/config.c b/PC/os2vacpp/config.c --- a/PC/os2vacpp/config.c +++ b/PC/os2vacpp/config.c @@ -91,7 +91,6 @@ {"_imp", initimp}, /* These entries are here for sys.builtin_module_names */ - {"__main__", NULL}, {"builtins", NULL}, {"sys", NULL}, diff --git a/Python/importlib.h b/Python/importlib.h index 7a83c0239cb1e9ca030daf74a03bfe3c6859b220..c3a60ef62dd7e8c77ab350d680a441c60903d845 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 20:02:51 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 20:02:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/f90c735e7699 changeset: 76580:f90c735e7699 parent: 76579:3bd60cc27664 parent: 76575:1c8a79c4c73e user: Brett Cannon date: Fri Apr 27 14:02:33 2012 -0400 summary: merge files: Tools/hg/hgtouch.py | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Tools/hg/hgtouch.py b/Tools/hg/hgtouch.py --- a/Tools/hg/hgtouch.py +++ b/Tools/hg/hgtouch.py @@ -7,15 +7,19 @@ In addition to the dependency syntax, #-comments are supported. """ +import errno import os def parse_config(repo): - configfile = repo.wjoin(".hgtouch") - if not os.path.exists(configfile): + try: + fp = repo.wfile(".hgtouch") + except IOError, e: + if e.errno != errno.ENOENT: + raise return {} result = {} - with open(configfile) as f: - for line in f: + with fp: + for line in fp: # strip comments line = line.split('#')[0].strip() if ':' not in line: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 21:07:41 2012 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 27 Apr 2012 21:07:41 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_decref_cached_keys_on_type_?= =?utf8?q?deallocation_=28=2313903=29?= Message-ID: http://hg.python.org/cpython/rev/a3beae842f13 changeset: 76581:a3beae842f13 user: Benjamin Peterson date: Fri Apr 27 15:07:36 2012 -0400 summary: decref cached keys on type deallocation (#13903) files: Objects/typeobject.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2593,6 +2593,9 @@ return update_slot(type, name); } +extern void +_PyDictKeys_DecRef(PyDictKeysObject *keys); + static void type_dealloc(PyTypeObject *type) { @@ -2616,6 +2619,8 @@ Py_XDECREF(et->ht_name); Py_XDECREF(et->ht_qualname); Py_XDECREF(et->ht_slots); + if (et->ht_cached_keys) + _PyDictKeys_DecRef(et->ht_cached_keys); Py_TYPE(type)->tp_free((PyObject *)type); } @@ -2791,9 +2796,6 @@ return 0; } -extern void -_PyDictKeys_DecRef(PyDictKeysObject *keys); - static int type_clear(PyTypeObject *type) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 21:31:51 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 21:31:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Use_None_?= =?utf8?q?in_sys=2Epath=5Fimporter=5Fcache_to_represent_no?= Message-ID: http://hg.python.org/cpython/rev/7025ee00dbf6 changeset: 76582:7025ee00dbf6 parent: 76580:f90c735e7699 user: Brett Cannon date: Fri Apr 27 15:30:58 2012 -0400 summary: Issue #14605: Use None in sys.path_importer_cache to represent no finder instead of using some (now non-existent) implicit finder. files: Lib/importlib/_bootstrap.py | 26 ++--------- Lib/importlib/test/import_/test_path.py | 28 ++--------- Lib/runpy.py | 9 +-- Misc/NEWS | 6 +- Modules/main.c | 2 +- Python/import.c | 10 +--- Python/importlib.h | Bin 7 files changed, 18 insertions(+), 63 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -766,17 +766,14 @@ except ImportError: continue else: - raise ImportError("no path hook found for {0}".format(path), - path=path) + return None @classmethod def _path_importer_cache(cls, path): """Get the finder for the path from sys.path_importer_cache. If the path is not in the cache, find the appropriate finder and cache - it. Because of NullImporter, some finder should be returned. The only - explicit fail case is if None is cached but the path cannot be used for - the default hook, for which ImportError is raised. + it. If no finder is available, store None. """ if path == '': @@ -786,15 +783,6 @@ except KeyError: finder = cls._path_hooks(path) sys.path_importer_cache[path] = finder - else: - if finder is None: - msg = ("'None' in sys.path_importer_cache[{!r}], so retrying " - "finder search; in future versions of Python 'None' " - "will represent no finder".format(path)) - _warnings.warn(msg, ImportWarning) - del sys.path_importer_cache[path] - finder = cls._path_hooks(path) - sys.path_importer_cache[path] = finder return finder @classmethod @@ -804,11 +792,8 @@ if path is None: path = sys.path for entry in path: - try: - finder = cls._path_importer_cache(entry) - except ImportError: - continue - if finder: + finder = cls._path_importer_cache(entry) + if finder is not None: loader = finder.find_module(fullname) if loader: return loader @@ -1192,6 +1177,5 @@ supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False), (SourceFileLoader, _suffix_list(1), True), (SourcelessFileLoader, _suffix_list(2), True)] - sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders), - _imp.NullImporter]) + sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)]) sys.meta_path.extend([BuiltinImporter, FrozenImporter, PathFinder]) diff --git a/Lib/importlib/test/import_/test_path.py b/Lib/importlib/test/import_/test_path.py --- a/Lib/importlib/test/import_/test_path.py +++ b/Lib/importlib/test/import_/test_path.py @@ -66,36 +66,18 @@ self.assertTrue(sys.path_importer_cache[path] is importer) def test_empty_path_hooks(self): - # Test that if sys.path_hooks is empty a warning is raised and - # PathFinder returns None. - # tried again (with a warning). + # Test that if sys.path_hooks is empty a warning is raised, + # sys.path_importer_cache gets None set, and PathFinder returns None. + path_entry = 'bogus_path' with util.import_state(path_importer_cache={}, path_hooks=[], - path=['bogus_path']): + path=[path_entry]): with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') self.assertIsNone(machinery.PathFinder.find_module('os')) - self.assertNotIn('os', sys.path_importer_cache) + self.assertIsNone(sys.path_importer_cache[path_entry]) self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, ImportWarning)) - def test_path_importer_cache_has_None_continues(self): - # Test that having None in sys.path_importer_cache causes the search to - # continue. - path = '' - module = '' - importer = util.mock_modules(module) - with util.import_state(path=['1', '2'], - path_importer_cache={'1': None, '2': importer}, - path_hooks=[imp.NullImporter]): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - loader = machinery.PathFinder.find_module(module) - self.assertTrue(loader is importer) - self.assertEqual(len(w), 1) - warned = w[0] - self.assertTrue(issubclass(warned.category, ImportWarning)) - self.assertIn(repr(None), str(warned.message)) - def test_path_importer_cache_empty_string(self): # The empty string should create a finder using the cwd. path = '' diff --git a/Lib/runpy.py b/Lib/runpy.py --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -9,6 +9,7 @@ # Written by Nick Coghlan # to implement PEP 338 (Executing Modules as Scripts) + import os import sys import imp @@ -206,11 +207,7 @@ except ImportError: pass else: - # The following check looks a bit odd. The trick is that - # NullImporter throws ImportError if the supplied path is a - # *valid* directory entry (and hence able to be handled - # by the standard import machinery) - importer = imp.NullImporter(path_name) + importer = None cache[path_name] = importer return importer @@ -237,7 +234,7 @@ if run_name is None: run_name = "" importer = _get_importer(path_name) - if isinstance(importer, imp.NullImporter): + if isinstance(importer, (type(None), imp.NullImporter)): # Not a valid sys.path entry, so run the code directly # execfile() doesn't help as we want to allow compiled files code = _get_code_from_file(path_name) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -14,9 +14,9 @@ sys.meta_path is found to be empty, raise ImportWarning. - Issue #14605: No longer have implicit entries in sys.path_hooks. If - sys.path_hooks is found to be empty, a warning will be raised. If None is - found in sys.path_importer_cache, a warning is raised and a search on - sys.path_hooks is attempted. + sys.path_hooks is found to be empty, a warning will be raised. None is now + inserted into sys.path_importer_cache if no finder was discovered. This also + means imp.NullImporter is no longer implicitly used. - Issue #13903: Implement PEP 412. Individual dictionary instances can now share their keys with other dictionaries. Classes take advantage of this to share diff --git a/Modules/main.c b/Modules/main.c --- a/Modules/main.c +++ b/Modules/main.c @@ -224,7 +224,7 @@ if (importer == NULL) goto error; - if (importer->ob_type == &PyNullImporter_Type) { + if (importer == Py_None) { Py_DECREF(argv0); Py_DECREF(importer); return -1; diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1186,15 +1186,7 @@ PyErr_Clear(); } if (importer == NULL) { - importer = PyObject_CallFunctionObjArgs( - (PyObject *)&PyNullImporter_Type, p, NULL - ); - if (importer == NULL) { - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - PyErr_Clear(); - return Py_None; - } - } + return Py_None; } if (importer != NULL) { int err = PyDict_SetItem(path_importer_cache, p, importer); diff --git a/Python/importlib.h b/Python/importlib.h index c3a60ef62dd7e8c77ab350d680a441c60903d845..c4080da005e8b4c5facc10e8ed3aaee297a890c0 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 21:31:52 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 21:31:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/cbaaf95476e7 changeset: 76583:cbaaf95476e7 parent: 76582:7025ee00dbf6 parent: 76581:a3beae842f13 user: Brett Cannon date: Fri Apr 27 15:31:45 2012 -0400 summary: merge files: Objects/typeobject.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2593,6 +2593,9 @@ return update_slot(type, name); } +extern void +_PyDictKeys_DecRef(PyDictKeysObject *keys); + static void type_dealloc(PyTypeObject *type) { @@ -2616,6 +2619,8 @@ Py_XDECREF(et->ht_name); Py_XDECREF(et->ht_qualname); Py_XDECREF(et->ht_slots); + if (et->ht_cached_keys) + _PyDictKeys_DecRef(et->ht_cached_keys); Py_TYPE(type)->tp_free((PyObject *)type); } @@ -2791,9 +2796,6 @@ return 0; } -extern void -_PyDictKeys_DecRef(PyDictKeysObject *keys); - static int type_clear(PyTypeObject *type) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 21:45:28 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 21:45:28 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314605=3A_Don=27t_e?= =?utf8?q?rror_out_if_get=5Fimporter=28=29_returns_None=2E?= Message-ID: http://hg.python.org/cpython/rev/141ed4b426e1 changeset: 76584:141ed4b426e1 user: Brett Cannon date: Fri Apr 27 15:45:15 2012 -0400 summary: Issue #14605: Don't error out if get_importer() returns None. files: Lib/pkgutil.py | 2 ++ Python/importlib.h | Bin 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -466,6 +466,8 @@ platform-specific special import locations such as the Windows registry. """ for importer in iter_importers(fullname): + if importer is None: + continue loader = importer.find_module(fullname) if loader is not None: return loader diff --git a/Python/importlib.h b/Python/importlib.h index c4080da005e8b4c5facc10e8ed3aaee297a890c0..cc3ddc43349236a87b80a231ff6a6b576251f89e GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 22:33:55 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 27 Apr 2012 22:33:55 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Optimize_=5FPyUnicode=5FFin?= =?utf8?q?dMaxChar=28=29_find_pure_ASCII_strings?= Message-ID: http://hg.python.org/cpython/rev/d27440b2f318 changeset: 76585:d27440b2f318 user: Victor Stinner date: Fri Apr 27 22:26:58 2012 +0200 summary: Optimize _PyUnicode_FindMaxChar() find pure ASCII strings files: Objects/unicodeobject.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1985,6 +1985,9 @@ if (start == end) return 127; + if (PyUnicode_IS_ASCII(unicode)) + return 127; + kind = PyUnicode_KIND(unicode); startptr = PyUnicode_DATA(unicode); endptr = (char *)startptr + end * kind; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 23:32:43 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 23:32:43 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Add_PEP_421_=28=22Add_sys=2Eim?= =?utf8?q?plementation=22=29_on_behalf_of_Eric_Snow=2E?= Message-ID: http://hg.python.org/peps/rev/89be6d29b35c changeset: 4315:89be6d29b35c user: Brett Cannon date: Fri Apr 27 17:32:38 2012 -0400 summary: Add PEP 421 ("Add sys.implementation") on behalf of Eric Snow. files: pep-0421.txt | 307 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 307 insertions(+), 0 deletions(-) diff --git a/pep-0421.txt b/pep-0421.txt new file mode 100644 --- /dev/null +++ b/pep-0421.txt @@ -0,0 +1,307 @@ +PEP: 421 +Title: Adding sys.implementation +Version: $Revision$ +Last-Modified: $Date$ +Author: Eric Snow +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 26-April-2012 +Post-History: 26-April-2012 + + +Abstract +======== + +This PEP introduces a new variable for the sys module: ``sys.implementation``. +The variable holds consolidated information about the implementation of +the running interpreter. Thus ``sys.implementation`` is the source to +which the standard library may look for implementation-specific +information. + +The proposal in this PEP is in line with a broader emphasis on making +Python friendlier to alternate implementations. It describes the new +variable and the constraints on what that variable contains. The PEP +also explains some immediate use cases for ``sys.implementation``. + + +Motivation +========== + +For a number of years now, the distinction between Python-the-language +and CPython (the reference implementation) has been growing. Most of +this change is due to the emergence of Jython, IronPython, and PyPy as +viable alternate implementations of Python. + +Consider, however, the nearly two decades of CPython-centric Python +(i.e. most of its existance). That focus had understandably contributed +to quite a few CPython-specific artifacts both in the standard library +and exposed in the interpreter. Though the core developers have made an +effort in recent years to address this, quite a few of the artifacts +remain. + +Part of the solution is presented in this PEP: a single namespace on +which to consolidate implementation specifics. This will help focus +efforts to differentiate the implementation specifics from the language. +Additionally, it will foster a multiple-implementation mindset. + + +Proposal +======== + +We will add ``sys.implementation``, in the sys module, as a namespace to +contain implementation-specific information. + +The contents of this namespace will remain fixed during interpreter +execution and through the course of an implementation version. This +ensures behaviors don't change between versions which depend on variables +in ``sys.implementation``. + +``sys.implementation`` is a dictionary, as opposed to any form of "named" +tuple (a la ``sys.version_info``). This is partly because it doesn't +have meaning as a sequence, and partly because it's a potentially more +variable data structure. + +The namespace will contain at least the variables described in the +`Required Variables`_ section below. However, implementations are free +to add other implementation information there. Some possible extra +variables are described in the `Other Possible Variables`_ section. + +This proposal takes a conservative approach in requiring only two +variables. As more become appropriate, they may be added with discretion. + + +Required Variables +-------------------- + +These are variables in ``sys.implementation`` on which the standard +library would rely, meaning they would need to be defined: + +name + the name of the implementation (case sensitive). + +version + the version of the implementation, as opposed to the version of the + language it implements. This would use a standard format, similar to + ``sys.version_info`` (see `Version Format`_). + + +Other Possible Variables +------------------------ + +These variables could be useful, but don't necessarily have a clear use +case presently: + +cache_tag + a string used for the PEP 3147 cache tag (e.g. 'cpython33' for + CPython 3.3). The name and version from above could be used to + compose this, though an implementation may want something else. + However, module caching is not a requirement of implementations, nor + is the use of cache tags. + +repository + the implementation's repository URL. + +repository_revision + the revision identifier for the implementation. + +build_toolchain + identifies the tools used to build the interpreter. + +url (or website) + the URL of the implementation's site. + +site_prefix + the preferred site prefix for this implementation. + +runtime + the run-time environment in which the interpreter is running. + +gc_type + the type of garbage collection used. + + +Version Format +-------------- + +XXX same as sys.version_info? + + +Rationale +========= + +The status quo for implementation-specific information gives us that +information in a more fragile, harder to maintain way. It's spread out +over different modules or inferred from other information, as we see with +``platform.python_implementation()``. + +This PEP is the main alternative to that approach. It consolidates the +implementation-specific information into a single namespace and makes +explicit that which was implicit. + +With the single-namespace-under-sys so straightforward, no alternatives +have been considered for this PEP. + +Discussion +========== + +The topic of ``sys.implementation`` came up on the python-ideas list in +2009, where the reception was broadly positive [1]_. I revived the +discussion recently while working on a pure-python ``imp.get_tag()`` [2]_. +The messages in `issue #14673`_ are also relevant. + + +Use-cases +========= + +``platform.python_implementation()`` +------------------------------------ + +"explicit is better than implicit" + +The platform module guesses the python implementation by looking for +clues in a couple different sys variables [3]_. However, this approach +is fragile. Beyond that, it's limited to those implementations that core +developers have blessed by special-casing them in the platform module. + +With ``sys.implementation`` the various implementations would +*explicitly* set the values in their own version of the sys module. + +Aside from the guessing, another concern is that the platform module is +part of the stdlib, which ideally would minimize implementation details +such as would be moved to ``sys.implementation``. + +Any overlap between ``sys.implementation`` and the platform module would +simply defer to ``sys.implementation`` (with the same interface in +platform wrapping it). + + +Cache Tag Generation in Frozen Importlib +---------------------------------------- + +PEP 3147 defined the use of a module cache and cache tags for file names. +The importlib bootstrap code, frozen into the Python binary as of 3.3, +uses the cache tags during the import process. Part of the project to +bootstrap importlib has been to clean out of Lib/import.c any code that +did not need to be there. + +The cache tag defined in Lib/import.c was hard-coded to +``"cpython" MAJOR MINOR`` [4]_. For importlib the options are either +hard-coding it in the same way, or guessing the implementation in the +same way as does ``platform.python_implementation()``. + +As long as the hard-coded tag is limited to CPython-specific code, it's +livable. However, inasmuch as other Python implementations use the +importlib code to work with the module cache, a hard-coded tag would +become a problem.. + +Directly using the platform module in this case is a non-starter. Any +module used in the importlib bootstrap must be built-in or frozen, +neither of which apply to the platform module. This is the point that +led to the recent interest in ``sys.implementation``. + +Regardless of how the implementation name is gotten, the version to use +for the cache tag is more likely to be the implementation version rather +than the language version. That implementation version is not readily +identified anywhere in the standard library. + + +Implementation-Specific Tests +----------------------------- + +XXX + +http://hg.python.org/cpython/file/2f563908ebc5/Lib/test/support.py#l509 +http://hg.python.org/cpython/file/2f563908ebc5/Lib/test/support.py#l1246 +http://hg.python.org/cpython/file/2f563908ebc5/Lib/test/support.py#l1252 +http://hg.python.org/cpython/file/2f563908ebc5/Lib/test/support.py#l1275 + + +Jython's ``os.name`` Hack +------------------------- + +XXX + +http://hg.python.org/cpython/file/2f563908ebc5/Lib/test/support.py#l512 + + +Impact on CPython +================= + +XXX + + +Feedback From Other Python Implementators +========================================= + +IronPython +---------- + +XXX + +Jython +------ + +XXX + +PyPy +---- + +XXX + + +Past Efforts +============ + +XXX PEP 3139 +XXX PEP 399 + + +Open Issues +=========== + +* What are the long-term objectives for sys.implementation? + + - pull in implementation detail from the main sys namespace and + elsewhere (PEP 3137 lite). + +* Alternatives to the approach dictated by this PEP? + +* ``sys.implementation`` as a proper namespace rather than a dict. It + would be it's own module or an instance of a concrete class. + + +Implementation +============== + +The implementatation of this PEP is covered in `issue #14673`_. + + +References +========== + +.. [1] http://mail.python.org/pipermail/python-dev/2009-October/092893.html + +.. [2] http://mail.python.org/pipermail/python-ideas/2012-April/014878.html + +.. [3] http://hg.python.org/cpython/file/2f563908ebc5/Lib/platform.py#l1247 + +.. [4] http://hg.python.org/cpython/file/2f563908ebc5/Python/import.c#l121 + +.. _issue #14673: http://bugs.python.org/issue14673 + + +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: http://hg.python.org/peps From python-checkins at python.org Fri Apr 27 23:33:07 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 23:33:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314646=3A_=5F=5Fimp?= =?utf8?b?b3J0X18oKSBub3cgc2V0cyBfX2xvYWRlcl9fIGlmIG5lZWQgYmUu?= Message-ID: http://hg.python.org/cpython/rev/496c68f90a03 changeset: 76586:496c68f90a03 parent: 76584:141ed4b426e1 user: Brett Cannon date: Fri Apr 27 17:27:14 2012 -0400 summary: Issue #14646: __import__() now sets __loader__ if need be. importlib.util.module_for_loader also will set __loader__ along with __package__. This is in conjunction to a forthcoming update to PEP 302 which will make these two attributes required for loaders to set. files: Doc/library/importlib.rst | 32 +++++++++++++++---- Lib/importlib/_bootstrap.py | 28 +++++++++++++++- Lib/importlib/test/test_util.py | 28 +++++++++++++++++ Misc/NEWS | 5 +++ Python/importlib.h | Bin 5 files changed, 83 insertions(+), 10 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -697,22 +697,30 @@ signature taking two positional arguments (e.g. ``load_module(self, module)``) for which the second argument will be the module **object** to be used by the loader. - Note that the decorator - will not work on static methods because of the assumption of two - arguments. + Note that the decorator will not work on static methods because of the + assumption of two arguments. The decorated method will take in the **name** of the module to be loaded as expected for a :term:`loader`. If the module is not found in :data:`sys.modules` then a new one is constructed with its - :attr:`__name__` attribute set. Otherwise the module found in - :data:`sys.modules` will be passed into the method. If an - exception is raised by the decorated method and a module was added to + :attr:`__name__` attribute set to **name**, :attr:`__loader__` set to + **self**, and :attr:`__package__` set if + :meth:`importlib.abc.InspectLoader.is_package` is defined for **self** and + does not raise :exc:`ImportError` for **name**. If a new module is not + needed then the module found in :data:`sys.modules` will be passed into the + method. + + If an exception is raised by the decorated method and a module was added to :data:`sys.modules` it will be removed to prevent a partially initialized module from being in left in :data:`sys.modules`. If the module was already in :data:`sys.modules` then it is left alone. Use of this decorator handles all the details of which module object a - loader should initialize as specified by :pep:`302`. + loader should initialize as specified by :pep:`302` as best as possible. + + .. versionchanged:: 3.3 + :attr:`__loader__` and :attr:`__package__` are automatically set + (when possible). .. decorator:: set_loader @@ -722,6 +730,12 @@ does nothing. It is assumed that the first positional argument to the wrapped method (i.e. ``self``) is what :attr:`__loader__` should be set to. + .. note:: + + It is recommended that :func:`module_for_loader` be used over this + decorator as it subsumes this functionality. + + .. decorator:: set_package A :term:`decorator` for a :term:`loader` to set the :attr:`__package__` @@ -736,3 +750,7 @@ attribute set and thus can be used by global level code during initialization. + .. note:: + + It is recommended that :func:`module_for_loader` be used over this + decorator as it subsumes this functionality. diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -257,9 +257,14 @@ The decorated function is passed the module to use instead of the module name. The module passed in to the function is either from sys.modules if - it already exists or is a new module which has __name__ set and is inserted - into sys.modules. If an exception is raised and the decorator created the - module it is subsequently removed from sys.modules. + it already exists or is a new module. If the module is new, then __name__ + is set the first argument to the method, __loader__ is set to self, and + __package__ is set accordingly (if self.is_package() is defined) will be set + before it is passed to the decorated function (if self.is_package() does + not work for the module it will be set post-load). + + If an exception is raised and the decorator created the module it is + subsequently removed from sys.modules. The decorator assumes that the decorated function takes the module name as the second argument. @@ -274,7 +279,18 @@ # infinite loop. module = _new_module(fullname) sys.modules[fullname] = module + module.__loader__ = self + try: + is_package = self.is_package(fullname) + except (ImportError, AttributeError): + pass + else: + if is_package: + module.__package__ = fullname + else: + module.__package__ = fullname.rpartition('.')[0] try: + # If __package__ was not set above, __import__() will do it later. return fxn(self, module, *args, **kwargs) except: if not is_reload: @@ -1012,6 +1028,12 @@ module.__package__ = module.__package__.rpartition('.')[0] except AttributeError: pass + # Set loader if need be. + if not hasattr(module, '__loader__'): + try: + module.__loader__ = loader + except AttributeError: + pass return module diff --git a/Lib/importlib/test/test_util.py b/Lib/importlib/test/test_util.py --- a/Lib/importlib/test/test_util.py +++ b/Lib/importlib/test/test_util.py @@ -79,6 +79,34 @@ given = self.return_module(name) self.assertTrue(given is module) + def test_attributes_set(self): + # __name__, __loader__, and __package__ should be set (when + # is_package() is defined; undefined implicitly tested elsewhere). + class FakeLoader: + def __init__(self, is_package): + self._pkg = is_package + def is_package(self, name): + return self._pkg + @util.module_for_loader + def load_module(self, module): + return module + + name = 'pkg.mod' + with test_util.uncache(name): + loader = FakeLoader(False) + module = loader.load_module(name) + self.assertEqual(module.__name__, name) + self.assertIs(module.__loader__, loader) + self.assertEqual(module.__package__, 'pkg') + + name = 'pkg.sub' + with test_util.uncache(name): + loader = FakeLoader(True) + module = loader.load_module(name) + self.assertEqual(module.__name__, name) + self.assertIs(module.__loader__, loader) + self.assertEqual(module.__package__, name) + class SetPackageTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #14646: __import__() sets __loader__ if the loader did not. + - Issue #14605: No longer have implicit entries in sys.meta_path. If sys.meta_path is found to be empty, raise ImportWarning. @@ -79,6 +81,9 @@ Library ------- +- Issue #14646: importlib.util.module_for_loader() now sets __loader__ and + __package__ (when possible). + - Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a test class that doesn't inherit from TestCase (i.e. a mixin). diff --git a/Python/importlib.h b/Python/importlib.h index cc3ddc43349236a87b80a231ff6a6b576251f89e..e9f5faf2fa9b7e239563aff1db46d6e1d70fcb88 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 23:33:07 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 23:33:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/69ea85992b3d changeset: 76587:69ea85992b3d parent: 76586:496c68f90a03 parent: 76585:d27440b2f318 user: Brett Cannon date: Fri Apr 27 17:27:33 2012 -0400 summary: merge files: Objects/unicodeobject.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1985,6 +1985,9 @@ if (start == end) return 127; + if (PyUnicode_IS_ASCII(unicode)) + return 127; + kind = PyUnicode_KIND(unicode); startptr = PyUnicode_DATA(unicode); endptr = (char *)startptr + end * kind; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 23:41:33 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 27 Apr 2012 23:41:33 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Require_=5F=5Floader=5F=5F_and?= =?utf8?q?_=5F=5Fpackage=5F=5F_to_be_set_by_loaders=2E?= Message-ID: http://hg.python.org/peps/rev/108e9e328481 changeset: 4316:108e9e328481 user: Brett Cannon date: Fri Apr 27 17:41:29 2012 -0400 summary: Require __loader__ and __package__ to be set by loaders. files: pep-0302.txt | 40 ++++++++++++++++++---------------------- 1 files changed, 18 insertions(+), 22 deletions(-) diff --git a/pep-0302.txt b/pep-0302.txt --- a/pep-0302.txt +++ b/pep-0302.txt @@ -273,25 +273,33 @@ be a list, but may be empty if __path__ has no further significance to the importer (more on this later). - - It should add an __loader__ attribute to the module, set to the - loader object. This is mostly for introspection, but can be used + - The __loader__ attribute must be set to the loader object. + This is mostly for introspection and reloading, but can be used for importer-specific extras, for example getting data associated with an importer. + - The __package__ attribute [10] must be set. + If the module is a Python module (as opposed to a built-in module or a dynamically loaded extension), it should execute the module's code in the module's global name space (module.__dict__). Here is a minimal pattern for a load_module() method: + # Consider using importlib.util.module_for_loader() to handle + # most of these details for you. def load_module(self, fullname): - ispkg, code = self._get_code(fullname) + code = self.get_code(fullname) + ispkg = self.is_package(fullname) mod = sys.modules.setdefault(fullname, imp.new_module(fullname)) mod.__file__ = "<%s>" % self.__class__.__name__ mod.__loader__ = self if ispkg: mod.__path__ = [] - exec code in mod.__dict__ + mod.__package__ = fullname + else: + mod.__package__ = fullname.rpartition('.')[0] + exec(code, mod.__dict__) return mod @@ -485,24 +493,9 @@ importer object, zipimport also adds an attribute "__loader__" to the module, containing the zipimport object used to load the module. If such an approach is used, it is important that client - code takes care not to break if the get_data method (or the - __loader__ attribute) is not available, so it is not clear that - this approach offers a general answer to the problem. - - Requiring loaders to set the module's __loader__ attribute means - that the loader will not get thrown away once the load is complete. - This increases memory usage, and stops loaders from being - lightweight, "throwaway" objects. As loader objects are not - required to offer any useful functionality (any such functionality, - such as the zipimport get_data() method mentioned above, is - optional) it is not clear that the __loader__ attribute will be - helpful, in practice. - - On the other hand, finder objects are mostly permanent, as they - live or are kept alive on sys.meta_path, sys.path_importer_cache, so - for a loader to keep a reference to the importer costs us nothing - extra. Whether loaders will ever need to carry so much independent - state for this to become a real issue is questionable. + code takes care not to break if the get_data method is not available, + so it is not clear that this approach offers a general answer to the + problem. It was suggested on python-dev that it would be useful to be able to receive a list of available modules from an importer and/or a list @@ -586,6 +579,9 @@ [9] PEP 338: Executing modules as scripts http://www.python.org/dev/peps/pep-0338/ + [10] PEP 366: Main module explicit relative imports + http://www.python.org/dev/peps/pep-0366/ + Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Apr 27 23:45:37 2012 From: python-checkins at python.org (victor.stinner) Date: Fri, 27 Apr 2012 23:45:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Simplify_and_optimize_forma?= =?utf8?q?tlong=28=29?= Message-ID: http://hg.python.org/cpython/rev/f4837725c50f changeset: 76588:f4837725c50f user: Victor Stinner date: Fri Apr 27 23:40:13 2012 +0200 summary: Simplify and optimize formatlong() * Remove _PyBytes_FormatLong(): inline it into formatlong() * the input type is always a long, so remove the code for bool * don't duplicate the string if the length does not change * Use PyUnicode_DATA() instead of _PyUnicode_AsString() files: Include/bytesobject.h | 2 - Objects/bytesobject.c | 143 ---------------------------- Objects/unicodeobject.c | 139 +++++++++++++++++++++++++- 3 files changed, 130 insertions(+), 154 deletions(-) diff --git a/Include/bytesobject.h b/Include/bytesobject.h --- a/Include/bytesobject.h +++ b/Include/bytesobject.h @@ -62,8 +62,6 @@ PyAPI_FUNC(void) PyBytes_ConcatAndDel(PyObject **, PyObject *); #ifndef Py_LIMITED_API PyAPI_FUNC(int) _PyBytes_Resize(PyObject **, Py_ssize_t); -PyAPI_FUNC(PyObject *) _PyBytes_FormatLong(PyObject*, int, int, - int, char**, int*); #endif PyAPI_FUNC(PyObject *) PyBytes_DecodeEscape(const char *, Py_ssize_t, const char *, Py_ssize_t, diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2860,149 +2860,6 @@ return 0; } -/* _PyBytes_FormatLong emulates the format codes d, u, o, x and X, and - * the F_ALT flag, for Python's long (unbounded) ints. It's not used for - * Python's regular ints. - * Return value: a new PyBytes*, or NULL if error. - * . *pbuf is set to point into it, - * *plen set to the # of chars following that. - * Caller must decref it when done using pbuf. - * The string starting at *pbuf is of the form - * "-"? ("0x" | "0X")? digit+ - * "0x"/"0X" are present only for x and X conversions, with F_ALT - * set in flags. The case of hex digits will be correct, - * There will be at least prec digits, zero-filled on the left if - * necessary to get that many. - * val object to be converted - * flags bitmask of format flags; only F_ALT is looked at - * prec minimum number of digits; 0-fill on left if needed - * type a character in [duoxX]; u acts the same as d - * - * CAUTION: o, x and X conversions on regular ints can never - * produce a '-' sign, but can for Python's unbounded ints. - */ -PyObject* -_PyBytes_FormatLong(PyObject *val, int flags, int prec, int type, - char **pbuf, int *plen) -{ - PyObject *result = NULL; - char *buf; - Py_ssize_t i; - int sign; /* 1 if '-', else 0 */ - int len; /* number of characters */ - Py_ssize_t llen; - int numdigits; /* len == numnondigits + numdigits */ - int numnondigits = 0; - - /* Avoid exceeding SSIZE_T_MAX */ - if (prec > INT_MAX-3) { - PyErr_SetString(PyExc_OverflowError, - "precision too large"); - return NULL; - } - - switch (type) { - case 'd': - case 'u': - /* Special-case boolean: we want 0/1 */ - if (PyBool_Check(val)) - result = PyNumber_ToBase(val, 10); - else - result = Py_TYPE(val)->tp_str(val); - break; - case 'o': - numnondigits = 2; - result = PyNumber_ToBase(val, 8); - break; - case 'x': - case 'X': - numnondigits = 2; - result = PyNumber_ToBase(val, 16); - break; - default: - assert(!"'type' not in [duoxX]"); - } - if (!result) - return NULL; - - buf = _PyUnicode_AsString(result); - if (!buf) { - Py_DECREF(result); - return NULL; - } - - /* To modify the string in-place, there can only be one reference. */ - if (Py_REFCNT(result) != 1) { - PyErr_BadInternalCall(); - return NULL; - } - llen = PyUnicode_GetLength(result); - if (llen > INT_MAX) { - PyErr_SetString(PyExc_ValueError, - "string too large in _PyBytes_FormatLong"); - return NULL; - } - len = (int)llen; - if (buf[len-1] == 'L') { - --len; - buf[len] = '\0'; - } - sign = buf[0] == '-'; - numnondigits += sign; - numdigits = len - numnondigits; - assert(numdigits > 0); - - /* Get rid of base marker unless F_ALT */ - if (((flags & F_ALT) == 0 && - (type == 'o' || type == 'x' || type == 'X'))) { - assert(buf[sign] == '0'); - assert(buf[sign+1] == 'x' || buf[sign+1] == 'X' || - buf[sign+1] == 'o'); - numnondigits -= 2; - buf += 2; - len -= 2; - if (sign) - buf[0] = '-'; - assert(len == numnondigits + numdigits); - assert(numdigits > 0); - } - - /* Fill with leading zeroes to meet minimum width. */ - if (prec > numdigits) { - PyObject *r1 = PyBytes_FromStringAndSize(NULL, - numnondigits + prec); - char *b1; - if (!r1) { - Py_DECREF(result); - return NULL; - } - b1 = PyBytes_AS_STRING(r1); - for (i = 0; i < numnondigits; ++i) - *b1++ = *buf++; - for (i = 0; i < prec - numdigits; i++) - *b1++ = '0'; - for (i = 0; i < numdigits; i++) - *b1++ = *buf++; - *b1 = '\0'; - Py_DECREF(result); - result = r1; - buf = PyBytes_AS_STRING(result); - len = numnondigits + prec; - } - - /* Fix up case for hex conversions. */ - if (type == 'X') { - /* Need to convert all lower case letters to upper case. - and need to convert 0x to 0X (and -0x to -0X). */ - for (i = 0; i < len; i++) - if (buf[i] >= 'a' && buf[i] <= 'x') - buf[i] -= 'a'-'A'; - } - *pbuf = buf; - *plen = len; - return result; -} - void PyBytes_Fini(void) { diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13438,19 +13438,140 @@ return result; } +/* formatlong() emulates the format codes d, u, o, x and X, and + * the F_ALT flag, for Python's long (unbounded) ints. It's not used for + * Python's regular ints. + * Return value: a new PyUnicodeObject*, or NULL if error. + * The output string is of the form + * "-"? ("0x" | "0X")? digit+ + * "0x"/"0X" are present only for x and X conversions, with F_ALT + * set in flags. The case of hex digits will be correct, + * There will be at least prec digits, zero-filled on the left if + * necessary to get that many. + * val object to be converted + * flags bitmask of format flags; only F_ALT is looked at + * prec minimum number of digits; 0-fill on left if needed + * type a character in [duoxX]; u acts the same as d + * + * CAUTION: o, x and X conversions on regular ints can never + * produce a '-' sign, but can for Python's unbounded ints. + */ static PyObject* formatlong(PyObject *val, int flags, int prec, int type) { + PyObject *result = NULL; char *buf; - int len; - PyObject *str; /* temporary string object. */ - PyObject *result; - - str = _PyBytes_FormatLong(val, flags, prec, type, &buf, &len); - if (!str) - return NULL; - result = PyUnicode_DecodeASCII(buf, len, NULL); - Py_DECREF(str); + Py_ssize_t i; + int sign; /* 1 if '-', else 0 */ + int len; /* number of characters */ + Py_ssize_t llen; + int numdigits; /* len == numnondigits + numdigits */ + int numnondigits = 0; + + /* Avoid exceeding SSIZE_T_MAX */ + if (prec > INT_MAX-3) { + PyErr_SetString(PyExc_OverflowError, + "precision too large"); + return NULL; + } + + assert(PyLong_Check(val)); + + switch (type) { + case 'd': + case 'u': + /* Special-case boolean: we want 0/1 */ + result = Py_TYPE(val)->tp_str(val); + break; + case 'o': + numnondigits = 2; + result = PyNumber_ToBase(val, 8); + break; + case 'x': + case 'X': + numnondigits = 2; + result = PyNumber_ToBase(val, 16); + break; + default: + assert(!"'type' not in [duoxX]"); + } + if (!result) + return NULL; + + assert(unicode_modifiable(result)); + assert(PyUnicode_IS_READY(result)); + assert(PyUnicode_IS_ASCII(result)); + + /* To modify the string in-place, there can only be one reference. */ + if (Py_REFCNT(result) != 1) { + PyErr_BadInternalCall(); + return NULL; + } + buf = PyUnicode_DATA(result); + llen = PyUnicode_GET_LENGTH(result); + if (llen > INT_MAX) { + PyErr_SetString(PyExc_ValueError, + "string too large in _PyBytes_FormatLong"); + return NULL; + } + len = (int)llen; + sign = buf[0] == '-'; + numnondigits += sign; + numdigits = len - numnondigits; + assert(numdigits > 0); + + /* Get rid of base marker unless F_ALT */ + if (((flags & F_ALT) == 0 && + (type == 'o' || type == 'x' || type == 'X'))) { + assert(buf[sign] == '0'); + assert(buf[sign+1] == 'x' || buf[sign+1] == 'X' || + buf[sign+1] == 'o'); + numnondigits -= 2; + buf += 2; + len -= 2; + if (sign) + buf[0] = '-'; + assert(len == numnondigits + numdigits); + assert(numdigits > 0); + } + + /* Fill with leading zeroes to meet minimum width. */ + if (prec > numdigits) { + PyObject *r1 = PyBytes_FromStringAndSize(NULL, + numnondigits + prec); + char *b1; + if (!r1) { + Py_DECREF(result); + return NULL; + } + b1 = PyBytes_AS_STRING(r1); + for (i = 0; i < numnondigits; ++i) + *b1++ = *buf++; + for (i = 0; i < prec - numdigits; i++) + *b1++ = '0'; + for (i = 0; i < numdigits; i++) + *b1++ = *buf++; + *b1 = '\0'; + Py_DECREF(result); + result = r1; + buf = PyBytes_AS_STRING(result); + len = numnondigits + prec; + } + + /* Fix up case for hex conversions. */ + if (type == 'X') { + /* Need to convert all lower case letters to upper case. + and need to convert 0x to 0X (and -0x to -0X). */ + for (i = 0; i < len; i++) + if (buf[i] >= 'a' && buf[i] <= 'x') + buf[i] -= 'a'-'A'; + } + if (!PyUnicode_Check(result) || len != PyUnicode_GET_LENGTH(result)) { + PyObject *unicode; + unicode = unicode_fromascii((unsigned char *)buf, len); + Py_DECREF(result); + result = unicode; + } return result; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Apr 27 23:52:35 2012 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 27 Apr 2012 23:52:35 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314666=3A_stop_mult?= =?utf8?q?iprocessing=27s_resource-sharing_thread_after_the_tests?= Message-ID: http://hg.python.org/cpython/rev/f163c4731c58 changeset: 76589:f163c4731c58 user: Antoine Pitrou date: Fri Apr 27 23:51:03 2012 +0200 summary: Issue #14666: stop multiprocessing's resource-sharing thread after the tests are done. Also, block delivery of signals to that thread. Patch by Richard Oudkerk. This will hopefully fix sporadic freezes on the FreeBSD 9.0 buildbot. files: Lib/multiprocessing/reduction.py | 29 +++++++++++++++++++- Lib/test/test_multiprocessing.py | 5 +++ 2 files changed, 33 insertions(+), 1 deletions(-) diff --git a/Lib/multiprocessing/reduction.py b/Lib/multiprocessing/reduction.py --- a/Lib/multiprocessing/reduction.py +++ b/Lib/multiprocessing/reduction.py @@ -40,6 +40,7 @@ import socket import threading import struct +import signal from multiprocessing import current_process from multiprocessing.util import register_after_fork, debug, sub_debug @@ -209,6 +210,7 @@ self._lock = threading.Lock() self._listener = None self._address = None + self._thread = None register_after_fork(self, ResourceSharer._afterfork) def register(self, send, close): @@ -227,6 +229,24 @@ c.send((key, os.getpid())) return c + def stop(self, timeout=None): + from .connection import Client + with self._lock: + if self._address is not None: + c = Client(self._address, authkey=current_process().authkey) + c.send(None) + c.close() + self._thread.join(timeout) + if self._thread.is_alive(): + sub_warn('ResourceSharer thread did not stop when asked') + self._listener.close() + self._thread = None + self._address = None + self._listener = None + for key, (send, close) in self._cache.items(): + close() + self._cache.clear() + def _afterfork(self): for key, (send, close) in self._cache.items(): close() @@ -239,6 +259,7 @@ self._listener.close() self._listener = None self._address = None + self._thread = None def _start(self): from .connection import Listener @@ -249,12 +270,18 @@ t = threading.Thread(target=self._serve) t.daemon = True t.start() + self._thread = t def _serve(self): + if hasattr(signal, 'pthread_sigmask'): + signal.pthread_sigmask(signal.SIG_BLOCK, range(1, signal.NSIG)) while 1: try: conn = self._listener.accept() - key, destination_pid = conn.recv() + msg = conn.recv() + if msg is None: + break + key, destination_pid = msg send, close = self._cache.pop(key) send(conn, destination_pid) close() diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -1966,6 +1966,11 @@ ALLOWED_TYPES = ('processes',) @classmethod + def tearDownClass(cls): + from multiprocessing.reduction import resource_sharer + resource_sharer.stop(timeout=5) + + @classmethod def _listener(cls, conn, families): for fam in families: l = cls.connection.Listener(family=fam) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 28 00:28:10 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 28 Apr 2012 00:28:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_my_previous_commit=3A_b?= =?utf8?q?ool_is_a_long=2C_restore_the_specical_case_for_bool?= Message-ID: http://hg.python.org/cpython/rev/7bacccd889c2 changeset: 76590:7bacccd889c2 user: Victor Stinner date: Sat Apr 28 00:25:34 2012 +0200 summary: Fix my previous commit: bool is a long, restore the specical case for bool files: Objects/unicodeobject.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13481,7 +13481,10 @@ case 'd': case 'u': /* Special-case boolean: we want 0/1 */ - result = Py_TYPE(val)->tp_str(val); + if (PyBool_Check(val)) + result = PyNumber_ToBase(val, 10); + else + result = Py_TYPE(val)->tp_str(val); break; case 'o': numnondigits = 2; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 28 03:21:32 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 28 Apr 2012 03:21:32 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Remove_the_unverifi?= =?utf8?q?ed_info_about_mach=5Ftimebase=5Finfo=28=29?= Message-ID: http://hg.python.org/peps/rev/4f03cfa6fd54 changeset: 4317:4f03cfa6fd54 user: Victor Stinner date: Sat Apr 28 03:21:26 2012 +0200 summary: PEP 418: Remove the unverified info about mach_timebase_info() files: pep-0418.txt | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -968,11 +968,9 @@ based on absolute elapsed time since system boot. It is not adjusted and cannot be set. -mach_timebase_info() gives a fraction to convert the clock value to a -number of nanoseconds. According to the documentation (`Technical Q&A -QA1398 `_), -mach_timebase_info() is always equal to one and never fails, even if -the function may fail according to its prototype. +mach_timebase_info() gives a fraction to convert the clock value to a number of +nanoseconds. See also the `Technical Q&A QA1398 +`_. mach_absolute_time() stops during a sleep on a PowerPC CPU, but not on an Intel CPU: `Different behaviour of mach_absolute_time() on i386/ppc -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Sat Apr 28 05:39:46 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 28 Apr 2012 05:39:46 +0200 Subject: [Python-checkins] Daily reference leaks (7bacccd889c2): sum=0 Message-ID: results for 7bacccd889c2 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogLdb3Uf', '-x'] From python-checkins at python.org Sat Apr 28 09:51:45 2012 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 28 Apr 2012 09:51:45 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Fix_markup?= Message-ID: http://hg.python.org/peps/rev/24d02504e664 changeset: 4318:24d02504e664 user: Raymond Hettinger date: Sat Apr 28 00:51:37 2012 -0700 summary: Fix markup files: pep-0008.txt | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -841,16 +841,20 @@ whenever they do something other than acquire and release resources. For example: - Yes: with conn.begin_transaction(): + Yes:: + + with conn.begin_transaction(): do_stuff_in_transaction(conn) - No: with conn: + No:: + + with conn: do_stuff_in_transaction(conn) - The latter example doesn't provide any information to indicate that - the __enter__ and __exit__ methods are doing something other than - closing the connection after a transaction. Being explicit is - important in this case. + The latter example doesn't provide any information to indicate that + the __enter__ and __exit__ methods are doing something other than + closing the connection after a transaction. Being explicit is + important in this case. - Use string methods instead of the string module. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 28 11:00:05 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 28 Apr 2012 11:00:05 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_Cleanup_the_glossar?= =?utf8?q?y?= Message-ID: http://hg.python.org/peps/rev/e0e9fbfe24ae changeset: 4319:e0e9fbfe24ae user: Victor Stinner date: Sat Apr 28 10:59:31 2012 +0200 summary: PEP 418: Cleanup the glossary * and are not terms of the glossary * remove the useless definition of duration * monotonic: reading a monotonic clock is not slower than other clock files: pep-0418.txt | 17 +++-------------- 1 files changed, 3 insertions(+), 14 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -610,14 +610,14 @@ :Clock: An instrument for measuring time. Different clocks have different - characteristics; for example, a clock with + characteristics; for example, a clock with nanosecond may start to after a few minutes, while a less precise clock remained accurate for days. This PEP is primarily concerned with clocks which use a unit of seconds. :Counter: A clock which increments each time a certain event occurs. A - counter is , but not . It can + counter is strictly monotonic, but not a monotonic clock. It can be used to generate a unique (and ordered) timestamp, but these timestamps cannot be mapped to ; tick creation may well be bursty, with several advances in the same millisecond followed @@ -630,12 +630,6 @@ when profiling, but they do not map directly to user response time, nor are they directly comparable to (real time) seconds. -:Duration: - Elapsed time. The difference between the starting and ending - times. A defined creates an implicit (and usually large) - duration. More precision can generally be provided for a - relatively small . - :Drift: The accumulated error against "true" time, as defined externally to the system. Drift may be due to imprecision, or to a difference @@ -657,12 +651,7 @@ Moving in at most one direction; for clocks, that direction is forward. The should also be , and should be convertible to a unit of seconds. The tradeoffs often include lack - of a defined or mapping to , and being more - expensive (in , power usage, or spent within - calls to the clock itself) to use. For example, the clock may - represent (a constant multiplied by) ticks of a specific quartz - timer on a specific CPU core, and calls would therefore require - synchronization between cores. + of a defined or mapping to . :Precision: The amount of deviation among measurements of the same physical -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 28 11:21:56 2012 From: python-checkins at python.org (sandro.tosi) Date: Sat, 28 Apr 2012 11:21:56 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0NDQ4?= =?utf8?q?=3A_add_reference_to_IANA_timezone_database=3B_thanks_to_Georg/N?= =?utf8?q?ick?= Message-ID: http://hg.python.org/cpython/rev/1e5a483248ce changeset: 76591:1e5a483248ce branch: 2.7 parent: 76576:3bac1e1a0e0d user: Sandro Tosi date: Sat Apr 28 11:19:11 2012 +0200 summary: Issue #14448: add reference to IANA timezone database; thanks to Georg/Nick suggestions files: Doc/library/datetime.rst | 15 +++++++++++---- 1 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1524,11 +1524,18 @@ .. seealso:: `pytz `_ - The Standard Library has no :class:`tzinfo` instances except for UTC, but - it exists a third-party library which brings Olson timezone database to - Python: `pytz`. + The standard library has no :class:`tzinfo` instances except for UTC, but + there exists a third-party library which brings the *IANA timezone + database* (also known as the Olson database) to Python: *pytz*. - `pytz` contains up-to-date information and its usage is recommended. + *pytz* contains up-to-date information and its usage is recommended. + + `IANA timezone database `_ + The Time Zone Database (often called tz or zoneinfo) contains code and + data that represent the history of local time for many representative + locations around the globe. It is updated periodically to reflect changes + made by political bodies to time zone boundaries, UTC offsets, and + daylight-saving rules. .. _strftime-strptime-behavior: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 28 11:21:57 2012 From: python-checkins at python.org (sandro.tosi) Date: Sat, 28 Apr 2012 11:21:57 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NDQ4?= =?utf8?q?=3A_add_reference_to_IANA_timezone_database=3B_thanks_to_Georg/N?= =?utf8?q?ick?= Message-ID: http://hg.python.org/cpython/rev/a5a0d47e6e78 changeset: 76592:a5a0d47e6e78 branch: 3.2 parent: 76554:ab3df6979bd0 user: Sandro Tosi date: Sat Apr 28 11:19:37 2012 +0200 summary: Issue #14448: add reference to IANA timezone database; thanks to Georg/Nick suggestions files: Doc/library/datetime.rst | 15 +++++++++++---- 1 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1560,11 +1560,18 @@ .. seealso:: `pytz `_ - The Standard Library has no :class:`tzinfo` instances except for UTC, but - it exists a third-party library which brings Olson timezone database to - Python: `pytz`. + The standard library has no :class:`tzinfo` instances except for UTC, but + there exists a third-party library which brings the *IANA timezone + database* (also known as the Olson database) to Python: *pytz*. - `pytz` contains up-to-date information and its usage is recommended. + *pytz* contains up-to-date information and its usage is recommended. + + `IANA timezone database `_ + The Time Zone Database (often called tz or zoneinfo) contains code and + data that represent the history of local time for many representative + locations around the globe. It is updated periodically to reflect changes + made by political bodies to time zone boundaries, UTC offsets, and + daylight-saving rules. .. _datetime-timezone: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 28 11:21:58 2012 From: python-checkins at python.org (sandro.tosi) Date: Sat, 28 Apr 2012 11:21:58 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314448=3A_merge_with_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/c91ed8dacf38 changeset: 76593:c91ed8dacf38 parent: 76590:7bacccd889c2 parent: 76592:a5a0d47e6e78 user: Sandro Tosi date: Sat Apr 28 11:19:59 2012 +0200 summary: Issue #14448: merge with 3.2 files: Doc/library/datetime.rst | 15 +++++++++++---- 1 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1599,11 +1599,18 @@ .. seealso:: `pytz `_ - The Standard Library has no :class:`tzinfo` instances except for UTC, but - it exists a third-party library which brings Olson timezone database to - Python: `pytz`. + The standard library has no :class:`tzinfo` instances except for UTC, but + there exists a third-party library which brings the *IANA timezone + database* (also known as the Olson database) to Python: *pytz*. - `pytz` contains up-to-date information and its usage is recommended. + *pytz* contains up-to-date information and its usage is recommended. + + `IANA timezone database `_ + The Time Zone Database (often called tz or zoneinfo) contains code and + data that represent the history of local time for many representative + locations around the globe. It is updated periodically to reflect changes + made by political bodies to time zone boundaries, UTC offsets, and + daylight-saving rules. .. _datetime-timezone: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 28 12:23:52 2012 From: python-checkins at python.org (sandro.tosi) Date: Sat, 28 Apr 2012 12:23:52 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0Njc2?= =?utf8?q?=3A_DeprecationWarning_is_ignored_too=3B_patch_by_Peter_Eisentra?= =?utf8?q?ut?= Message-ID: http://hg.python.org/cpython/rev/0ad724738f6a changeset: 76594:0ad724738f6a branch: 2.7 parent: 76591:1e5a483248ce user: Sandro Tosi date: Sat Apr 28 12:20:57 2012 +0200 summary: Issue #14676: DeprecationWarning is ignored too; patch by Peter Eisentraut files: Doc/library/warnings.rst | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -167,7 +167,8 @@ the command-line options passed to :option:`-W` and calls to :func:`filterwarnings`. -* :exc:`PendingDeprecationWarning`, and :exc:`ImportWarning` are ignored. +* :exc:`DeprecationWarning` and :exc:`PendingDeprecationWarning`, and + :exc:`ImportWarning` are ignored. * :exc:`BytesWarning` is ignored unless the :option:`-b` option is given once or twice; in this case this warning is either printed (``-b``) or turned into an -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 28 12:24:10 2012 From: python-checkins at python.org (eric.smith) Date: Sat, 28 Apr 2012 12:24:10 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Clarifaction_about_creating_na?= =?utf8?q?mespace_packages=2E_Thanks_Carl_Meyer=2E?= Message-ID: http://hg.python.org/peps/rev/b6dc6b727a9b changeset: 4320:b6dc6b727a9b user: Eric V. Smith date: Sat Apr 28 06:23:39 2012 -0400 summary: Clarifaction about creating namespace packages. Thanks Carl Meyer. files: pep-0420.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -122,8 +122,8 @@ * If not, but ``foo`` is found and is a directory, it is recorded. If the scan along the parent path completes without finding a module -or package, then a namespace package is created. The new namespace -package: +or package and at least one directory was recorded, then a namespace +package is created. The new namespace package: * Has a ``__file__`` attribute set to the first directory that was found during the scan, including the trailing path separator. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Apr 28 12:53:02 2012 From: python-checkins at python.org (sandro.tosi) Date: Sat, 28 Apr 2012 12:53:02 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_refer_to_file?= =?utf8?q?=2Ereadline=28=29_in_stdtypes_doc=3B_thanks_to_Mihai_Capot=C4=83?= =?utf8?q?_from_docs=40?= Message-ID: http://hg.python.org/cpython/rev/707905b3f8df changeset: 76595:707905b3f8df branch: 2.7 user: Sandro Tosi date: Sat Apr 28 12:50:42 2012 +0200 summary: refer to file.readline() in stdtypes doc; thanks to Mihai Capot? from docs@ files: Doc/library/stdtypes.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2378,7 +2378,7 @@ make a :keyword:`for` loop the most efficient way of looping over the lines of a file (a very common operation), the :meth:`~file.next` method uses a hidden read-ahead buffer. As a consequence of using a read-ahead buffer, combining :meth:`~file.next` - with other file methods (like :meth:`readline`) does not work right. However, + with other file methods (like :meth:`~file.readline`) does not work right. However, using :meth:`seek` to reposition the file to an absolute position will flush the read-ahead buffer. @@ -2420,7 +2420,7 @@ .. method:: file.readlines([sizehint]) - Read until EOF using :meth:`readline` and return a list containing the lines + Read until EOF using :meth:`~file.readline` and return a list containing the lines thus read. If the optional *sizehint* argument is present, instead of reading up to EOF, whole lines totalling approximately *sizehint* bytes (possibly after rounding up to an internal buffer size) are read. Objects @@ -2500,7 +2500,7 @@ add line separators.) Files support the iterator protocol. Each iteration returns the same result as -``file.readline()``, and iteration ends when the :meth:`readline` method returns +:meth:`~file.readline`, and iteration ends when the :meth:`~file.readline` method returns an empty string. File objects also offer a number of other interesting attributes. These are not -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Apr 28 23:48:34 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 28 Apr 2012 23:48:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Time_doc=3A_documentation_t?= =?utf8?q?hat_the_CLOCK=5F*_constants_and_clock=5F*=28=29_functions_are?= Message-ID: http://hg.python.org/cpython/rev/49675de23013 changeset: 76596:49675de23013 parent: 76593:c91ed8dacf38 user: Victor Stinner date: Sat Apr 28 23:47:33 2012 +0200 summary: Time doc: documentation that the CLOCK_* constants and clock_*() functions are not always available. files: Doc/library/time.rst | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -141,6 +141,8 @@ Return the resolution (precision) of the specified clock *clk_id*. + Availability: Unix. + .. versionadded:: 3.3 @@ -148,6 +150,8 @@ Return the time of the specified clock *clk_id*. + Availability: Unix. + .. versionadded:: 3.3 @@ -155,6 +159,8 @@ Set the time of the specified clock *clk_id*. + Availability: Unix. + .. versionadded:: 3.3 @@ -164,6 +170,8 @@ hardware source, and may give close to nanosecond resolution. CLOCK_HIGHRES is the nonadjustable, high-resolution clock. + Availability: Solaris. + .. versionadded:: 3.3 @@ -172,6 +180,8 @@ Clock that cannot be set and represents monotonic time since some unspecified starting point. + Availability: Unix. + .. versionadded:: 3.3 @@ -189,6 +199,8 @@ High-resolution per-process timer from the CPU. + Availability: Unix. + .. versionadded:: 3.3 @@ -197,6 +209,8 @@ System-wide real-time clock. Setting this clock requires appropriate privileges. + Availability: Unix. + .. versionadded:: 3.3 @@ -204,6 +218,8 @@ Thread-specific CPU-time clock. + Availability: Unix. + .. versionadded:: 3.3 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 01:43:18 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 29 Apr 2012 01:43:18 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_time=2Eget=5Fclock?= =?utf8?q?=5Finfo=28=29_has_no_more_optional_keys=2C_all_keys_are_mandator?= =?utf8?q?y?= Message-ID: http://hg.python.org/peps/rev/7da3a166c084 changeset: 4321:7da3a166c084 user: Victor Stinner date: Sun Apr 29 01:42:18 2012 +0200 summary: PEP 418: time.get_clock_info() has no more optional keys, all keys are mandatory files: pep-0418.txt | 19 +++++++------------ 1 files changed, 7 insertions(+), 12 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -116,18 +116,13 @@ Return a dictionary with the following keys: -* Mandatory keys: - - * ``"implementation"`` (str): name of the underlying operating system - function. Examples: ``"QueryPerformanceCounter()"``, - ``"clock_gettime(CLOCK_REALTIME)"``. - * ``"resolution"`` (float): resolution in seconds of the clock. - * ``"is_monotonic"`` (bool): True if the clock cannot go backward. - -* Optional keys: - - * ``"is_adjusted"`` (bool): True if the clock is adjusted (e.g. by a - NTP daemon). + * ``"implementation"`` (str): name of the underlying operating system + function. Examples: ``"QueryPerformanceCounter()"``, + ``"clock_gettime(CLOCK_REALTIME)"``. + * ``"resolution"`` (float): resolution in seconds of the clock. + * ``"is_monotonic"`` (bool): True if the clock cannot go backward. + * ``"is_adjusted"`` (bool): True if the clock is adjusted (e.g. by a + NTP daemon). time.monotonic() -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 29 02:27:43 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 29 Apr 2012 02:27:43 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_PEP_418=3A_time=2Eget=5Fclock?= =?utf8?q?=5Finfo=28=29_now_returns_an_object?= Message-ID: http://hg.python.org/peps/rev/a9a6a0851544 changeset: 4322:a9a6a0851544 user: Victor Stinner date: Sun Apr 29 02:26:42 2012 +0200 summary: PEP 418: time.get_clock_info() now returns an object files: pep-0418.txt | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -114,15 +114,15 @@ * ``"process_time"``: ``time.process_time()`` * ``"time"``: ``time.time()`` -Return a dictionary with the following keys: +Return a ``time.clock_info`` object which has the following attributes: - * ``"implementation"`` (str): name of the underlying operating system + * ``implementation`` (str): name of the underlying operating system function. Examples: ``"QueryPerformanceCounter()"``, ``"clock_gettime(CLOCK_REALTIME)"``. - * ``"resolution"`` (float): resolution in seconds of the clock. - * ``"is_monotonic"`` (bool): True if the clock cannot go backward. - * ``"is_adjusted"`` (bool): True if the clock is adjusted (e.g. by a + * ``is_monotonic`` (bool): True if the clock cannot go backward. + * ``is_adjusted`` (bool): True if the clock is adjusted (e.g. by a NTP daemon). + * ``resolution`` (float): resolution in seconds of the clock. time.monotonic() -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Apr 29 02:44:13 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 29 Apr 2012 02:44:13 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314428=2C_=2314397?= =?utf8?q?=3A_Implement_the_PEP_418?= Message-ID: http://hg.python.org/cpython/rev/76d2e0761d18 changeset: 76597:76d2e0761d18 user: Victor Stinner date: Sun Apr 29 02:41:27 2012 +0200 summary: Issue #14428, #14397: Implement the PEP 418 * Rename time.steady() to time.monotonic() * On Windows, time.monotonic() uses GetTickCount/GetTickCount64() instead of QueryPerformanceCounter() * time.monotonic() uses CLOCK_HIGHRES if available * Add time.get_clock_info(), time.perf_counter() and time.process_time() functions files: Doc/library/time.rst | 85 +++- Doc/whatsnew/3.3.rst | 18 +- Include/pytime.h | 14 + Lib/queue.py | 5 +- Lib/test/test_time.py | 107 +++++- Lib/threading.py | 6 +- Misc/NEWS | 4 + Modules/timemodule.c | 557 ++++++++++++++++++++++++----- Python/pytime.c | 62 ++- 9 files changed, 727 insertions(+), 131 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -155,6 +155,30 @@ .. versionadded:: 3.3 +.. class:: clock_info + + Clock information object created by :func:`get_clock_info`. + + .. attribute:: implementation + + name of the underlying C function used to get the clock value + + .. attribute:: is_monotonic + + ``True`` if the clock cannot go backward, ``False`` otherwise + + .. attribute:: is_adjusted + + ``True`` if the clock can be adjusted (e.g. by a NTP daemon), + ``False`` otherwise + + .. attribute:: resolution + + Resolution of the clock in seconds (:class:`float`) + + .. versionadded:: 3.3 + + .. function:: clock_settime(clk_id, time) Set the time of the specified clock *clk_id*. @@ -236,6 +260,22 @@ Nonzero if a DST timezone is defined. +.. function:: get_clock_info(name) + + Get information on the specified clock as a :class:`clock_info` object. + + Supported clock names: + + + * ``'clock'``: :func:`time.clock` + * ``'monotonic'``: :func:`time.monotonic` + * ``'perf_counter'``: :func:`time.perf_counter` + * ``'process_time'``: :func:`time.process_time` + * ``'time'``: :func:`time.time` + + .. versionadded:: 3.3 + + .. function:: gmtime([secs]) Convert a time expressed in seconds since the epoch to a :class:`struct_time` in @@ -265,20 +305,43 @@ The earliest date for which it can generate a time is platform-dependent. -.. function:: steady(strict=False) +.. function:: monotonic() - .. index:: - single: benchmarking + Monotonic clock, i.e. cannot go backward. It is not affected by system + clock updates. The reference point of the returned value is undefined, so + that only the difference between the results of consecutive calls is valid + and is a number of seconds. - Return the current time as a floating point number expressed in seconds. - This clock advances at a steady rate relative to real time and it may not be - adjusted. The reference point of the returned value is undefined so only the - difference of consecutive calls is valid. + On Windows versions older than Vista, :func:`monotonic` detects + :c:func:`GetTickCount` integer overflow (32 bits, roll-over after 49.7 + days). It increases an internal epoch (reference time by) 2\ :sup:`32` each + time that an overflow is detected. The epoch is stored in the process-local + state and so the value of :func:`monotonic` may be different in two Python + processes running for more than 49 days. On more recent versions of Windows + and on other operating systems, :func:`monotonic` is system-wide. - If available, a monotonic clock is used. By default, - the function falls back to another clock if the monotonic clock failed or is - not available. If *strict* is True, raise an :exc:`OSError` on error or - :exc:`NotImplementedError` if no monotonic clock is available. + Availability: Windows, Mac OS X, Linux, FreeBSD, OpenBSD, Solaris. + + .. versionadded:: 3.3 + + +.. function:: perf_counter() + + Performance counter with the highest available resolution to measure a short + duration. It does include time elapsed during sleep and is system-wide. + The reference point of the returned value is undefined, so that only the + difference between the results of consecutive calls is valid and is a number + of seconds. + + .. versionadded:: 3.3 + + +.. function:: process_time() + + Sum of the system and user CPU time of the current process. It does not + include time elapsed during sleep. It is process-wide by definition. The + reference point of the returned value is undefined, so that only the + difference between the results of consecutive calls is valid. .. versionadded:: 3.3 diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1059,13 +1059,21 @@ time ---- -The :mod:`time` module has new functions: +The :pep:`418` added new functions to the :mod:`time` module: -* :func:`~time.clock_getres` and :func:`~time.clock_gettime` functions and - ``CLOCK_xxx`` constants. -* :func:`~time.steady`. +* :func:`~time.get_clock_info`: Get information on a clock. +* :func:`~time.monotonic`: Monotonic clock (cannot go backward), not affected + by system clock updates. +* :func:`~time.perf_counter`: Performance counter with the highest available + resolution to measure a short duration. +* :func:`~time.process_time`: Sum of the system and user CPU time of the + current process. -(Contributed by Victor Stinner in :issue:`10278`) +Other new functions: + +* :func:`~time.clock_getres`, :func:`~time.clock_gettime` and + :func:`~time.clock_settime` functions with ``CLOCK_xxx`` constants. + (Contributed by Victor Stinner in :issue:`10278`) types diff --git a/Include/pytime.h b/Include/pytime.h --- a/Include/pytime.h +++ b/Include/pytime.h @@ -22,11 +22,25 @@ } _PyTime_timeval; #endif +/* Structure used by time.get_clock_info() */ +typedef struct { + const char *implementation; + int is_monotonic; + int is_adjusted; + double resolution; +} _Py_clock_info_t; + /* Similar to POSIX gettimeofday but cannot fail. If system gettimeofday * fails or is not available, fall back to lower resolution clocks. */ PyAPI_FUNC(void) _PyTime_gettimeofday(_PyTime_timeval *tp); +/* Similar to _PyTime_gettimeofday() but retrieve also information on the + * clock used to get the current time. */ +PyAPI_FUNC(void) _PyTime_gettimeofday_info( + _PyTime_timeval *tp, + _Py_clock_info_t *info); + #define _PyTime_ADD_SECONDS(tv, interval) \ do { \ tv.tv_usec += (long) (((long) interval - interval) * 1000000); \ diff --git a/Lib/queue.py b/Lib/queue.py --- a/Lib/queue.py +++ b/Lib/queue.py @@ -6,7 +6,10 @@ import dummy_threading as threading from collections import deque from heapq import heappush, heappop -from time import steady as time +try: + from time import monotonic as time +except ImportError: + from time import time __all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue'] diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -5,6 +5,10 @@ import sysconfig import sys import platform +try: + import threading +except ImportError: + threading = None # Max year is only limited by the size of C int. SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4 @@ -23,9 +27,20 @@ time.timezone time.tzname + def test_time(self): + time.time() + info = time.get_clock_info('time') + self.assertEqual(info.is_monotonic, False) + if sys.platform != 'win32': + self.assertEqual(info.is_adjusted, True) + def test_clock(self): time.clock() + info = time.get_clock_info('clock') + self.assertEqual(info.is_monotonic, True) + self.assertEqual(info.is_adjusted, False) + @unittest.skipUnless(hasattr(time, 'clock_gettime'), 'need time.clock_gettime()') def test_clock_realtime(self): @@ -56,7 +71,9 @@ except PermissionError: pass - self.assertRaises(OSError, time.clock_settime, time.CLOCK_MONOTONIC, 0) + if hasattr(time, 'CLOCK_MONOTONIC'): + self.assertRaises(OSError, + time.clock_settime, time.CLOCK_MONOTONIC, 0) def test_conversions(self): self.assertEqual(time.ctime(self.t), @@ -342,23 +359,69 @@ pass self.assertEqual(time.strftime('%Z', tt), tzname) - def test_steady(self): - t1 = time.steady() + @unittest.skipUnless(hasattr(time, 'monotonic'), + 'need time.monotonic') + def test_monotonic(self): + t1 = time.monotonic() time.sleep(0.1) - t2 = time.steady() + t2 = time.monotonic() dt = t2 - t1 - # may fail if the system clock was changed self.assertGreater(t2, t1) self.assertAlmostEqual(dt, 0.1, delta=0.2) - def test_steady_strict(self): + info = time.get_clock_info('monotonic') + self.assertEqual(info.is_monotonic, True) + if sys.platform == 'linux': + self.assertEqual(info.is_adjusted, True) + else: + self.assertEqual(info.is_adjusted, False) + + def test_perf_counter(self): + time.perf_counter() + + def test_process_time(self): + start = time.process_time() + time.sleep(0.1) + stop = time.process_time() + self.assertLess(stop - start, 0.01) + + info = time.get_clock_info('process_time') + self.assertEqual(info.is_monotonic, True) + self.assertEqual(info.is_adjusted, False) + + @unittest.skipUnless(threading, + 'need threading') + def test_process_time_threads(self): + class BusyThread(threading.Thread): + def run(self): + while not self.stop: + pass + + thread = BusyThread() + thread.stop = False + t1 = time.process_time() + thread.start() + time.sleep(0.2) + t2 = time.process_time() + thread.stop = True + thread.join() + self.assertGreater(t2 - t1, 0.1) + + @unittest.skipUnless(hasattr(time, 'monotonic'), + 'need time.monotonic') + @unittest.skipUnless(hasattr(time, 'clock_settime'), + 'need time.clock_settime') + def test_monotonic_settime(self): + t1 = time.monotonic() + realtime = time.clock_gettime(time.CLOCK_REALTIME) + # jump backward with an offset of 1 hour try: - t1 = time.steady(strict=True) - except OSError as err: - self.skipTest("the monotonic clock failed: %s" % err) - except NotImplementedError: - self.skipTest("no monotonic clock available") - t2 = time.steady(strict=True) + time.clock_settime(time.CLOCK_REALTIME, realtime - 3600) + except PermissionError as err: + self.skipTest(err) + t2 = time.monotonic() + time.clock_settime(time.CLOCK_REALTIME, realtime) + # monotonic must not be affected by system clock updates self.assertGreaterEqual(t2, t1) def test_localtime_failure(self): @@ -378,6 +441,26 @@ self.assertRaises(OSError, time.localtime, invalid_time_t) self.assertRaises(OSError, time.ctime, invalid_time_t) + def test_get_clock_info(self): + clocks = ['clock', 'perf_counter', 'process_time', 'time'] + if hasattr(time, 'monotonic'): + clocks.append('monotonic') + + for name in clocks: + info = time.get_clock_info(name) + #self.assertIsInstance(info, dict) + self.assertIsInstance(info.implementation, str) + self.assertNotEqual(info.implementation, '') + self.assertIsInstance(info.is_monotonic, bool) + self.assertIsInstance(info.resolution, float) + # 0.0 < resolution <= 1.0 + self.assertGreater(info.resolution, 0.0) + self.assertLessEqual(info.resolution, 1.0) + self.assertIsInstance(info.is_adjusted, bool) + + self.assertRaises(ValueError, time.get_clock_info, 'xxx') + + class TestLocale(unittest.TestCase): def setUp(self): self.oldloc = locale.setlocale(locale.LC_ALL) diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -3,7 +3,11 @@ import sys as _sys import _thread -from time import steady as _time, sleep as _sleep +from time import sleep as _sleep +try: + from time import monotonic as _time +except ImportError: + from time import time as _time from traceback import format_exc as _format_exc from _weakrefset import WeakSet diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -81,6 +81,10 @@ Library ------- +- Issue #14428: Implement the PEP 418. Add time.get_clock_info(), + time.perf_counter() and time.process_time() functions, and rename + time.steady() to time.monotonic(). + - Issue #14646: importlib.util.module_for_loader() now sets __loader__ and __package__ (when possible). diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -4,9 +4,17 @@ #include +#ifdef HAVE_SYS_TIMES_H +#include +#endif + #ifdef HAVE_SYS_TYPES_H #include -#endif /* HAVE_SYS_TYPES_H */ +#endif + +#if defined(HAVE_SYS_RESOURCE_H) +#include +#endif #ifdef QUICKWIN #include @@ -45,12 +53,16 @@ /* Forward declarations */ static int floatsleep(double); -static PyObject* floattime(void); +static PyObject* floattime(_Py_clock_info_t *info); + +#ifdef MS_WINDOWS +static OSVERSIONINFOEX winver; +#endif static PyObject * time_time(PyObject *self, PyObject *unused) { - return floattime(); + return floattime(NULL); } PyDoc_STRVAR(time_doc, @@ -70,7 +82,7 @@ #endif static PyObject * -pyclock(void) +floatclock(_Py_clock_info_t *info) { clock_t value; value = clock(); @@ -80,15 +92,22 @@ "or its value cannot be represented"); return NULL; } + if (info) { + info->implementation = "clock()"; + info->resolution = 1.0 / (double)CLOCKS_PER_SEC; + info->is_monotonic = 1; + info->is_adjusted = 0; + } return PyFloat_FromDouble((double)value / CLOCKS_PER_SEC); } #endif /* HAVE_CLOCK */ #if defined(MS_WINDOWS) && !defined(__BORLANDC__) +#define WIN32_PERF_COUNTER /* Win32 has better clock replacement; we have our own version, due to Mark Hammond and Tim Peters */ -static PyObject * -win32_clock(int fallback) +static int +win_perf_counter(_Py_clock_info_t *info, PyObject **result) { static LONGLONG cpu_frequency = 0; static LONGLONG ctrStart; @@ -102,28 +121,41 @@ if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) { /* Unlikely to happen - this works on all intel machines at least! Revert to clock() */ - if (fallback) - return pyclock(); - else - return PyErr_SetFromWindowsErr(0); + *result = NULL; + return -1; } cpu_frequency = freq.QuadPart; } QueryPerformanceCounter(&now); diff = (double)(now.QuadPart - ctrStart); - return PyFloat_FromDouble(diff / (double)cpu_frequency); + if (info) { + info->implementation = "QueryPerformanceCounter()"; + info->resolution = 1.0 / (double)cpu_frequency; + info->is_monotonic = 1; + info->is_adjusted = 0; + } + *result = PyFloat_FromDouble(diff / (double)cpu_frequency); + return 0; } #endif -#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK) +#if defined(WIN32_PERF_COUNTER) || defined(HAVE_CLOCK) +#define PYCLOCK +static PyObject* +pyclock(_Py_clock_info_t *info) +{ +#ifdef WIN32_PERF_COUNTER + PyObject *res; + if (win_perf_counter(info, &res) == 0) + return res; +#endif + return floatclock(info); +} + static PyObject * time_clock(PyObject *self, PyObject *unused) { -#if defined(MS_WINDOWS) && !defined(__BORLANDC__) - return win32_clock(1); -#else - return pyclock(); -#endif + return pyclock(NULL); } PyDoc_STRVAR(clock_doc, @@ -150,7 +182,6 @@ PyErr_SetFromErrno(PyExc_IOError); return NULL; } - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } @@ -787,11 +818,74 @@ should not be relied on."); #endif /* HAVE_WORKING_TZSET */ +#if defined(MS_WINDOWS) || defined(__APPLE__) \ + || (defined(HAVE_CLOCK_GETTIME) \ + && (defined(CLOCK_HIGHRES) || defined(CLOCK_MONOTONIC))) +#define PYMONOTONIC +#endif + +#ifdef PYMONOTONIC static PyObject* -steady_clock(int strict) +pymonotonic(_Py_clock_info_t *info) { -#if defined(MS_WINDOWS) && !defined(__BORLANDC__) - return win32_clock(!strict); +#if defined(MS_WINDOWS) + static ULONGLONG (*GetTickCount64) (void) = NULL; + static ULONGLONG (CALLBACK *Py_GetTickCount64)(void); + static int has_getickcount64 = -1; + double result; + + if (has_getickcount64 == -1) { + /* GetTickCount64() was added to Windows Vista */ + if (winver.dwMajorVersion >= 6) { + HINSTANCE hKernel32; + hKernel32 = GetModuleHandleW(L"KERNEL32"); + *(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32, + "GetTickCount64"); + has_getickcount64 = (Py_GetTickCount64 != NULL); + } + else + has_getickcount64 = 0; + } + + if (has_getickcount64) { + ULONGLONG ticks; + ticks = Py_GetTickCount64(); + result = (double)ticks * 1e-3; + } + else { + static DWORD last_ticks = 0; + static DWORD n_overflow = 0; + DWORD ticks; + + ticks = GetTickCount(); + if (ticks < last_ticks) + n_overflow++; + last_ticks = ticks; + + result = ldexp(n_overflow, 32); + result += ticks; + result *= 1e-3; + } + + if (info) { + DWORD timeAdjustment, timeIncrement; + BOOL isTimeAdjustmentDisabled, ok; + if (has_getickcount64) + info->implementation = "GetTickCount64()"; + else + info->implementation = "GetTickCount()"; + info->is_monotonic = 1; + ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, + &isTimeAdjustmentDisabled); + if (!ok) { + PyErr_SetFromWindowsErr(0); + return NULL; + } + info->resolution = timeIncrement * 1e-7; + info->is_adjusted = 0; + } + return PyFloat_FromDouble(result); + #elif defined(__APPLE__) static mach_timebase_info_data_t timebase; uint64_t time; @@ -805,88 +899,338 @@ time = mach_absolute_time(); secs = (double)time * timebase.numer / timebase.denom * 1e-9; + if (info) { + info->implementation = "mach_absolute_time()"; + info->resolution = (double)timebase.numer / timebase.denom * 1e-9; + info->is_monotonic = 1; + info->is_adjusted = 0; + } + return PyFloat_FromDouble(secs); - return PyFloat_FromDouble(secs); -#elif defined(HAVE_CLOCK_GETTIME) - static int steady_clk_index = 0; - static int monotonic_clk_index = 0; - int *clk_index; - clockid_t steady_clk_ids[] = { -#ifdef CLOCK_MONOTONIC_RAW - CLOCK_MONOTONIC_RAW, +#elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_HIGHRES) || defined(CLOCK_MONOTONIC)) + struct timespec tp; +#ifdef CLOCK_HIGHRES + const clockid_t clk_id = CLOCK_HIGHRES; + const char *function = "clock_gettime(CLOCK_HIGHRES)"; +#else + const clockid_t clk_id = CLOCK_MONOTONIC; + const char *function = "clock_gettime(CLOCK_MONOTONIC)"; #endif - CLOCK_MONOTONIC, - CLOCK_REALTIME - }; - clockid_t monotonic_clk_ids[] = { -#ifdef CLOCK_MONOTONIC_RAW - CLOCK_MONOTONIC_RAW, -#endif - CLOCK_MONOTONIC - }; - clockid_t *clk_ids; - int clk_ids_len; - int ret; - struct timespec tp; - if (strict) { - clk_index = &monotonic_clk_index; - clk_ids = monotonic_clk_ids; - clk_ids_len = Py_ARRAY_LENGTH(monotonic_clk_ids); - } - else { - clk_index = &steady_clk_index; - clk_ids = steady_clk_ids; - clk_ids_len = Py_ARRAY_LENGTH(steady_clk_ids); - } - - while (0 <= *clk_index) { - clockid_t clk_id = clk_ids[*clk_index]; - ret = clock_gettime(clk_id, &tp); - if (ret == 0) - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); - - (*clk_index)++; - if (clk_ids_len <= *clk_index) - (*clk_index) = -1; - } - if (strict) { + if (clock_gettime(clk_id, &tp) != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } - return floattime(); + + if (info) { + struct timespec res; + info->is_monotonic = 1; + info->implementation = function; +#if (defined(linux) || defined(__linux) || defined(__linux__)) \ + && !defined(CLOCK_HIGHRES) + /* CLOCK_MONOTONIC is adjusted on Linux */ + info->is_adjusted = 1; #else - if (strict) { - PyErr_SetString(PyExc_NotImplementedError, - "no steady clock available on your platform"); - return NULL; + info->is_adjusted = 0; +#endif + if (clock_getres(clk_id, &res) == 0) + info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + else + info->resolution = 1e-9; } - return floattime(); + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); #endif } static PyObject * -time_steady(PyObject *self, PyObject *args, PyObject *kwargs) +time_monotonic(PyObject *self, PyObject *unused) { - static char *kwlist[] = {"strict", NULL}; - int strict = 0; + return pymonotonic(NULL); +} - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, "|i:steady", kwlist, - &strict)) +PyDoc_STRVAR(monotonic_doc, +"monotonic() -> float\n\ +\n\ +Monotonic clock, cannot go backward."); +#endif /* PYMONOTONIC */ + +static PyObject* +perf_counter(_Py_clock_info_t *info) +{ +#if defined(WIN32_PERF_COUNTER) || defined(PYMONOTONIC) + PyObject *res; +#endif +#if defined(WIN32_PERF_COUNTER) + static int use_perf_counter = 1; +#endif +#ifdef PYMONOTONIC + static int use_monotonic = 1; +#endif + +#ifdef WIN32_PERF_COUNTER + if (use_perf_counter) { + if (win_perf_counter(info, &res) == 0) + return res; + use_perf_counter = 0; + } +#endif + +#ifdef PYMONOTONIC + if (use_monotonic) { + res = pymonotonic(info); + if (res != NULL) + return res; + use_monotonic = 0; + PyErr_Clear(); + } +#endif + + return floattime(info); +} + +static PyObject * +time_perf_counter(PyObject *self, PyObject *unused) +{ + return perf_counter(NULL); +} + +PyDoc_STRVAR(perf_counter_doc, +"perf_counter() -> float\n\ +\n\ +Performance counter for benchmarking."); + +static PyObject* +py_process_time(_Py_clock_info_t *info) +{ +#if defined(MS_WINDOWS) + HANDLE process; + FILETIME creation_time, exit_time, kernel_time, user_time; + ULARGE_INTEGER large; + double total; + BOOL ok; + + process = GetCurrentProcess(); + ok = GetProcessTimes(process, &creation_time, &exit_time, &kernel_time, &user_time); + if (!ok) + return PyErr_SetFromWindowsErr(0); + + large.u.LowPart = kernel_time.dwLowDateTime; + large.u.HighPart = kernel_time.dwHighDateTime; + total = (double)large.QuadPart; + large.u.LowPart = user_time.dwLowDateTime; + large.u.HighPart = user_time.dwHighDateTime; + total += (double)large.QuadPart; + if (info) { + info->implementation = "GetProcessTimes()"; + info->resolution = 1e-7; + info->is_monotonic = 1; + info->is_adjusted = 0; + } + return PyFloat_FromDouble(total * 1e-7); +#else + +#if defined(HAVE_SYS_RESOURCE_H) + struct rusage ru; +#endif +#ifdef HAVE_TIMES + struct tms t; + static long ticks_per_second = -1; +#endif + +#if defined(HAVE_CLOCK_GETTIME) \ + && (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF)) + struct timespec tp; +#ifdef CLOCK_PROF + const clockid_t clk_id = CLOCK_PROF; + const char *function = "clock_gettime(CLOCK_PROF)"; +#else + const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID; + const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)"; +#endif + + if (clock_gettime(clk_id, &tp) == 0) { + if (info) { + struct timespec res; + info->implementation = function; + info->is_monotonic = 1; + info->is_adjusted = 0; + if (clock_getres(clk_id, &res) == 0) + info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + else + info->resolution = 1e-9; + } + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + } +#endif + +#if defined(HAVE_SYS_RESOURCE_H) + if (getrusage(RUSAGE_SELF, &ru) == 0) { + double total; + total = ru.ru_utime.tv_sec + ru.ru_utime.tv_usec * 1e-6; + total += ru.ru_stime.tv_sec + ru.ru_stime.tv_usec * 1e-6; + if (info) { + info->implementation = "getrusage(RUSAGE_SELF)"; + info->is_monotonic = 1; + info->is_adjusted = 0; + info->resolution = 1e-6; + } + return PyFloat_FromDouble(total); + } +#endif + +#ifdef HAVE_TIMES + if (times(&t) != (clock_t)-1) { + double total; + + if (ticks_per_second == -1) { +#if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) + ticks_per_second = sysconf(_SC_CLK_TCK); + if (ticks_per_second < 1) + ticks_per_second = -1; +#elif defined(HZ) + ticks_per_second = HZ; +#else + ticks_per_second = 60; /* magic fallback value; may be bogus */ +#endif + } + + if (ticks_per_second != -1) { + total = (double)t.tms_utime / ticks_per_second; + total += (double)t.tms_stime / ticks_per_second; + if (info) { + info->implementation = "times()"; + info->is_monotonic = 1; + info->is_adjusted = 0; + info->resolution = 1.0 / ticks_per_second; + } + return PyFloat_FromDouble(total); + } + } +#endif + + return floatclock(info); +#endif +} + +static PyObject * +time_process_time(PyObject *self, PyObject *unused) +{ + return py_process_time(NULL); +} + +PyDoc_STRVAR(process_time_doc, +"process_time() -> float\n\ +\n\ +Process time for profiling: sum of the kernel and user-space CPU time."); + + +static PyTypeObject ClockInfoType; + +PyDoc_STRVAR(ClockInfo_docstring, + "Clock information"); + +static PyStructSequence_Field ClockInfo_fields[] = { + {"implementation", "name of the underlying C function " + "used to get the clock value"}, + {"is_monotonic", "True if the clock cannot go backward, False otherwise"}, + {"is_adjusted", "True if the clock can be adjusted " + "(e.g. by a NTP daemon), False otherwise"}, + {"resolution", "resolution of the clock in seconds"}, + {NULL, NULL} +}; + +static PyStructSequence_Desc ClockInfo_desc = { + "time.clock_info", + ClockInfo_docstring, + ClockInfo_fields, + 4, +}; + +static PyObject * +time_get_clock_info(PyObject *self, PyObject *args) +{ + char *name; + PyObject *obj; + _Py_clock_info_t info; + PyObject *result; + + if (!PyArg_ParseTuple(args, "s:get_clock_info", &name)) return NULL; - return steady_clock(strict); +#ifdef Py_DEBUG + info.implementation = NULL; + info.is_monotonic = -1; + info.is_adjusted = -1; + info.resolution = -1.0; +#else + info.implementation = ""; + info.is_monotonic = 0; + info.is_adjusted = 0; + info.resolution = 1.0; +#endif + + if (strcmp(name, "time") == 0) + obj = floattime(&info); +#ifdef PYCLOCK + else if (strcmp(name, "clock") == 0) + obj = pyclock(&info); +#endif +#ifdef PYMONOTONIC + else if (strcmp(name, "monotonic") == 0) + obj = pymonotonic(&info); +#endif + else if (strcmp(name, "perf_counter") == 0) + obj = perf_counter(&info); + else if (strcmp(name, "process_time") == 0) + obj = py_process_time(&info); + else { + PyErr_SetString(PyExc_ValueError, "unknown clock"); + return NULL; + } + if (obj == NULL) + return NULL; + Py_DECREF(obj); + + result = PyStructSequence_New(&ClockInfoType); + if (result == NULL) + return NULL; + + assert(info.implementation != NULL); + obj = PyUnicode_FromString(info.implementation); + if (obj == NULL) + goto error; + PyStructSequence_SET_ITEM(result, 0, obj); + + assert(info.is_monotonic != -1); + obj = PyBool_FromLong(info.is_monotonic); + if (obj == NULL) + goto error; + PyStructSequence_SET_ITEM(result, 1, obj); + + assert(info.is_adjusted != -1); + obj = PyBool_FromLong(info.is_adjusted); + if (obj == NULL) + goto error; + PyStructSequence_SET_ITEM(result, 2, obj); + + assert(info.resolution > 0.0); + assert(info.resolution <= 1.0); + obj = PyFloat_FromDouble(info.resolution); + if (obj == NULL) + goto error; + PyStructSequence_SET_ITEM(result, 3, obj); + + return result; + +error: + Py_DECREF(result); + return NULL; } -PyDoc_STRVAR(steady_doc, -"steady(strict=False) -> float\n\ +PyDoc_STRVAR(get_clock_info_doc, +"get_clock_info(name: str) -> dict\n\ \n\ -Return the current time as a floating point number expressed in seconds.\n\ -This clock advances at a steady rate relative to real time and it may not\n\ -be adjusted. The reference point of the returned value is undefined so only\n\ -the difference of consecutive calls is valid."); - +Get information of the specified clock."); static void PyInit_timezone(PyObject *m) { @@ -977,10 +1321,8 @@ #endif /* __CYGWIN__ */ #endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/ -#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETRES) -#ifdef CLOCK_REALTIME +#if defined(HAVE_CLOCK_GETTIME) PyModule_AddIntMacro(m, CLOCK_REALTIME); -#endif #ifdef CLOCK_MONOTONIC PyModule_AddIntMacro(m, CLOCK_MONOTONIC); #endif @@ -1002,7 +1344,7 @@ static PyMethodDef time_methods[] = { {"time", time_time, METH_NOARGS, time_doc}, -#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK) +#ifdef PYCLOCK {"clock", time_clock, METH_NOARGS, clock_doc}, #endif #ifdef HAVE_CLOCK_GETTIME @@ -1018,8 +1360,6 @@ #ifdef HAVE_MKTIME {"mktime", time_mktime, METH_O, mktime_doc}, #endif - {"steady", (PyCFunction)time_steady, METH_VARARGS|METH_KEYWORDS, - steady_doc}, #ifdef HAVE_STRFTIME {"strftime", time_strftime, METH_VARARGS, strftime_doc}, #endif @@ -1027,6 +1367,12 @@ #ifdef HAVE_WORKING_TZSET {"tzset", time_tzset, METH_NOARGS, tzset_doc}, #endif +#ifdef PYMONOTONIC + {"monotonic", time_monotonic, METH_NOARGS, monotonic_doc}, +#endif + {"process_time", time_process_time, METH_NOARGS, process_time_doc}, + {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, + {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, {NULL, NULL} /* sentinel */ }; @@ -1104,6 +1450,20 @@ if (!initialized) { PyStructSequence_InitType(&StructTimeType, &struct_time_type_desc); + + /* initialize ClockInfoType */ + PyStructSequence_InitType(&ClockInfoType, &ClockInfo_desc); + Py_INCREF(&ClockInfoType); + PyModule_AddObject(m, "clock_info", (PyObject*)&ClockInfoType); + +#ifdef MS_WINDOWS + winver.dwOSVersionInfoSize = sizeof(winver); + if (!GetVersionEx((OSVERSIONINFO*)&winver)) { + Py_DECREF(m); + PyErr_SetFromWindowsErr(0); + return NULL; + } +#endif } Py_INCREF(&StructTimeType); PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType); @@ -1112,7 +1472,7 @@ } static PyObject* -floattime(void) +floattime(_Py_clock_info_t *info) { _PyTime_timeval t; #ifdef HAVE_CLOCK_GETTIME @@ -1123,10 +1483,21 @@ because it would require to link Python to the rt (real-time) library, at least on Linux */ ret = clock_gettime(CLOCK_REALTIME, &tp); - if (ret == 0) + if (ret == 0) { + if (info) { + struct timespec res; + info->implementation = "clock_gettime(CLOCK_REALTIME)"; + info->is_monotonic = 0; + info->is_adjusted = 1; + if (clock_getres(CLOCK_REALTIME, &res) == 0) + info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + else + info->resolution = 1e-9; + } return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + } #endif - _PyTime_gettimeofday(&t); + _PyTime_gettimeofday_info(&t, info); return PyFloat_FromDouble((double)t.tv_sec + t.tv_usec * 1e-6); } diff --git a/Python/pytime.c b/Python/pytime.c --- a/Python/pytime.c +++ b/Python/pytime.c @@ -18,8 +18,8 @@ extern int ftime(struct timeb *); #endif -void -_PyTime_gettimeofday(_PyTime_timeval *tp) +static void +pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) { #ifdef MS_WINDOWS FILETIME system_time; @@ -35,6 +35,20 @@ microseconds = large.QuadPart / 10 - 11644473600000000; tp->tv_sec = microseconds / 1000000; tp->tv_usec = microseconds % 1000000; + if (info) { + DWORD timeAdjustment, timeIncrement; + BOOL isTimeAdjustmentDisabled; + + info->implementation = "GetSystemTimeAsFileTime()"; + info->is_monotonic = 0; + (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, + &isTimeAdjustmentDisabled); + info->resolution = timeIncrement * 1e-7; + if (isTimeAdjustmentDisabled) + info->is_adjusted = 0; + else + info->is_adjusted = 1; + } #else /* There are three ways to get the time: (1) gettimeofday() -- resolution in microseconds @@ -46,14 +60,22 @@ Note: clock resolution does not imply clock accuracy! */ #ifdef HAVE_GETTIMEOFDAY + int err; #ifdef GETTIMEOFDAY_NO_TZ - if (gettimeofday(tp) == 0) + err = gettimeofday(tp); +#else + err = gettimeofday(tp, (struct timezone *)NULL); +#endif + if (err == 0) { + if (info) { + info->implementation = "gettimeofday()"; + info->resolution = 1e-6; + info->is_monotonic = 0; + info->is_adjusted = 1; + } return; -#else /* !GETTIMEOFDAY_NO_TZ */ - if (gettimeofday(tp, (struct timezone *)NULL) == 0) - return; -#endif /* !GETTIMEOFDAY_NO_TZ */ -#endif /* !HAVE_GETTIMEOFDAY */ + } +#endif /* HAVE_GETTIMEOFDAY */ #if defined(HAVE_FTIME) { @@ -61,15 +83,39 @@ ftime(&t); tp->tv_sec = t.time; tp->tv_usec = t.millitm * 1000; + if (info) { + info->implementation = "ftime()"; + info->resolution = 1e-3; + info->is_monotonic = 0; + info->is_adjusted = 1; + } } #else /* !HAVE_FTIME */ tp->tv_sec = time(NULL); tp->tv_usec = 0; + if (info) { + info->implementation = "time()"; + info->resolution = 1.0; + info->is_monotonic = 0; + info->is_adjusted = 1; + } #endif /* !HAVE_FTIME */ #endif /* MS_WINDOWS */ } +void +_PyTime_gettimeofday(_PyTime_timeval *tp) +{ + pygettimeofday(tp, NULL); +} + +void +_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info) +{ + pygettimeofday(tp, info); +} + static void error_time_t_overflow(void) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 02:53:39 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 29 Apr 2012 02:53:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Close_=2314309=3A_Deprecate?= =?utf8?q?_time=2Eclock=28=29?= Message-ID: http://hg.python.org/cpython/rev/314c3faea2fb changeset: 76598:314c3faea2fb user: Victor Stinner date: Sun Apr 29 02:52:39 2012 +0200 summary: Close #14309: Deprecate time.clock() Use time.perf_counter() or time.process_time() instead. files: Doc/library/time.rst | 5 +++++ Doc/whatsnew/3.3.rst | 3 +++ Misc/NEWS | 3 +++ 3 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -136,6 +136,11 @@ :c:func:`QueryPerformanceCounter`. The resolution is typically better than one microsecond. + .. deprecated:: 3.3 + The behaviour of this function depends on the platform: use + :func:`perf_counter` or :func:`process_time` instead, depending on your + requirements, to have a well defined behaviour. + .. function:: clock_getres(clk_id) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1188,6 +1188,9 @@ the ANSI code page anymore and to support any filename. * :issue:`13988`: The :mod:`xml.etree.cElementTree` module is deprecated. The accelerator is used automatically whenever available. +* The behaviour of :func:`time.clock` depends on the platform: use the new + :func:`time.perf_counter` or :func:`time.process_time` function instead, + depending on your requirements, to have a well defined behaviour. Deprecated functions and types of the C API diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -81,6 +81,9 @@ Library ------- +- Issue #14309: Deprecate time.clock(), use time.perf_counter() or + time.process_time() instead. + - Issue #14428: Implement the PEP 418. Add time.get_clock_info(), time.perf_counter() and time.process_time() functions, and rename time.steady() to time.monotonic(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 03:04:16 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 29 Apr 2012 03:04:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314428=3A_Use_the_n?= =?utf8?q?ew_time=2Eperf=5Fcounter=28=29_and_time=2Eprocess=5Ftime=28=29_f?= =?utf8?q?unctions?= Message-ID: http://hg.python.org/cpython/rev/bd195749c0a2 changeset: 76599:bd195749c0a2 user: Victor Stinner date: Sun Apr 29 03:01:20 2012 +0200 summary: Issue #14428: Use the new time.perf_counter() and time.process_time() functions * Replace "time.clock on windows, or time.time" with time.perf_counter() * profile module: only use time.process_time() instead of trying different functions providing the process time * timeit module: use time.perf_counter() by default, time.time() and time.clock() can still be used using --time and --clock options * pybench program: use time.perf_counter() by default, add support for the new time.process_time() and time.perf_counter() functions, but stay backward compatible. Use also time.get_clock_info() to display information of the timer. files: Doc/includes/mp_benchmarks.py | 6 +--- Lib/idlelib/ColorDelegator.py | 4 +- Lib/profile.py | 36 +--------------------- Lib/test/reperf.py | 4 +- Lib/test/sortperf.py | 4 +- Lib/timeit.py | 12 +----- Tools/pybench/pybench.py | 21 ++++++++++++- 7 files changed, 32 insertions(+), 55 deletions(-) diff --git a/Doc/includes/mp_benchmarks.py b/Doc/includes/mp_benchmarks.py --- a/Doc/includes/mp_benchmarks.py +++ b/Doc/includes/mp_benchmarks.py @@ -6,16 +6,12 @@ # import time -import sys import multiprocessing import threading import queue import gc -if sys.platform == 'win32': - _timer = time.clock -else: - _timer = time.time +_timer = time.perf_counter delta = 1 diff --git a/Lib/idlelib/ColorDelegator.py b/Lib/idlelib/ColorDelegator.py --- a/Lib/idlelib/ColorDelegator.py +++ b/Lib/idlelib/ColorDelegator.py @@ -149,9 +149,9 @@ self.stop_colorizing = False self.colorizing = True if DEBUG: print("colorizing...") - t0 = time.clock() + t0 = time.perf_counter() self.recolorize_main() - t1 = time.clock() + t1 = time.perf_counter() if DEBUG: print("%.3f seconds" % (t1-t0)) finally: self.colorizing = False diff --git a/Lib/profile.py b/Lib/profile.py --- a/Lib/profile.py +++ b/Lib/profile.py @@ -83,26 +83,6 @@ else: return prof.print_stats(sort) -if hasattr(os, "times"): - def _get_time_times(timer=os.times): - t = timer() - return t[0] + t[1] - -# Using getrusage(3) is better than clock(3) if available: -# on some systems (e.g. FreeBSD), getrusage has a higher resolution -# Furthermore, on a POSIX system, returns microseconds, which -# wrap around after 36min. -_has_res = 0 -try: - import resource - resgetrusage = lambda: resource.getrusage(resource.RUSAGE_SELF) - def _get_time_resource(timer=resgetrusage): - t = timer() - return t[0] + t[1] - _has_res = 1 -except ImportError: - pass - class Profile: """Profiler class. @@ -155,20 +135,8 @@ self.bias = bias # Materialize in local dict for lookup speed. if not timer: - if _has_res: - self.timer = resgetrusage - self.dispatcher = self.trace_dispatch - self.get_time = _get_time_resource - elif hasattr(time, 'clock'): - self.timer = self.get_time = time.clock - self.dispatcher = self.trace_dispatch_i - elif hasattr(os, 'times'): - self.timer = os.times - self.dispatcher = self.trace_dispatch - self.get_time = _get_time_times - else: - self.timer = self.get_time = time.time - self.dispatcher = self.trace_dispatch_i + self.timer = self.get_time = time.process_time + self.dispatcher = self.trace_dispatch_i else: self.timer = timer t = self.timer() # test out timer function diff --git a/Lib/test/reperf.py b/Lib/test/reperf.py --- a/Lib/test/reperf.py +++ b/Lib/test/reperf.py @@ -9,13 +9,13 @@ timefunc(10, p.findall, s) def timefunc(n, func, *args, **kw): - t0 = time.clock() + t0 = time.perf_counter() try: for i in range(n): result = func(*args, **kw) return result finally: - t1 = time.clock() + t1 = time.perf_counter() if n > 1: print(n, "times", end=' ') print(func.__name__, "%.3f" % (t1-t0), "CPU seconds") diff --git a/Lib/test/sortperf.py b/Lib/test/sortperf.py --- a/Lib/test/sortperf.py +++ b/Lib/test/sortperf.py @@ -57,9 +57,9 @@ sys.stdout.flush() def doit(L): - t0 = time.clock() + t0 = time.perf_counter() L.sort() - t1 = time.clock() + t1 = time.perf_counter() print("%6.2f" % (t1-t0), end=' ') flush() diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -15,8 +15,8 @@ -n/--number N: how many times to execute 'statement' (default: see below) -r/--repeat N: how many times to repeat the timer (default 3) -s/--setup S: statement to be executed once initially (default 'pass') - -t/--time: use time.time() (default on Unix) - -c/--clock: use time.clock() (default on Windows) + -t/--time: use time.time() + -c/--clock: use time.clock() -v/--verbose: print raw timing results; repeat for more digits precision -h/--help: print this usage message and exit --: separate options from statement, use when statement starts with - @@ -66,13 +66,7 @@ dummy_src_name = "" default_number = 1000000 default_repeat = 3 - -if sys.platform == "win32": - # On Windows, the best timer is time.clock() - default_timer = time.clock -else: - # On most other platforms the best timer is time.time() - default_timer = time.time +default_timer = time.perf_counter # Don't change the indentation of the template; the reindent() calls # in Timer.__init__() depend on setup being indented 4 spaces and stmt diff --git a/Tools/pybench/pybench.py b/Tools/pybench/pybench.py --- a/Tools/pybench/pybench.py +++ b/Tools/pybench/pybench.py @@ -73,11 +73,15 @@ # Timer types TIMER_TIME_TIME = 'time.time' +TIMER_TIME_PROCESS_TIME = 'time.process_time' +TIMER_TIME_PERF_COUNTER = 'time.perf_counter' TIMER_TIME_CLOCK = 'time.clock' TIMER_SYSTIMES_PROCESSTIME = 'systimes.processtime' # Choose platform default timer -if sys.platform[:3] == 'win': +if hasattr(time, 'perf_counter'): + TIMER_PLATFORM_DEFAULT = TIMER_TIME_PERF_COUNTER +elif sys.platform[:3] == 'win': # On WinXP this has 2.5ms resolution TIMER_PLATFORM_DEFAULT = TIMER_TIME_CLOCK else: @@ -93,6 +97,10 @@ if timertype == TIMER_TIME_TIME: return time.time + elif timertype == TIMER_TIME_PROCESS_TIME: + return time.process_time + elif timertype == TIMER_TIME_PERF_COUNTER: + return time.perf_counter elif timertype == TIMER_TIME_CLOCK: return time.clock elif timertype == TIMER_SYSTIMES_PROCESSTIME: @@ -866,7 +874,18 @@ print('* using timer: systimes.processtime (%s)' % \ systimes.SYSTIMES_IMPLEMENTATION) else: + # Check that the clock function does exist + try: + get_timer(timer) + except TypeError: + print("* Error: Unknown timer: %s" % timer) + return + print('* using timer: %s' % timer) + if hasattr(time, 'get_clock_info'): + info = time.get_clock_info(timer[5:]) + print('* timer: resolution=%s, implementation=%s' + % (info.resolution, info.implementation)) print() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 03:53:28 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 03:53:28 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0MTU1OiBhZGQg?= =?utf8?q?a_note_about_=5Cb=2E?= Message-ID: http://hg.python.org/cpython/rev/142297db28f1 changeset: 76600:142297db28f1 branch: 2.7 parent: 76595:707905b3f8df user: Ezio Melotti date: Sun Apr 29 04:46:34 2012 +0300 summary: #14155: add a note about \b. files: Doc/library/re.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -398,6 +398,9 @@ \r \t \v \x \\ +(Note that ``\b`` is used to represent word boundaries, and means "backspace" +only inside character classes.) + Octal escapes are included in a limited form: If the first digit is a 0, or if there are three octal digits, it is considered an octal escape. Otherwise, it is a group reference. As for string literals, octal escapes are always at most -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 03:53:29 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 03:53:29 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0MTU1OiBhZGQg?= =?utf8?q?a_note_about_=5Cb=2E?= Message-ID: http://hg.python.org/cpython/rev/f4b167309bee changeset: 76601:f4b167309bee branch: 3.2 parent: 76592:a5a0d47e6e78 user: Ezio Melotti date: Sun Apr 29 04:52:30 2012 +0300 summary: #14155: add a note about \b. files: Doc/library/re.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -417,6 +417,9 @@ \r \t \v \x \\ +(Note that ``\b`` is used to represent word boundaries, and means "backspace" +only inside character classes.) + Octal escapes are included in a limited form. If the first digit is a 0, or if there are three octal digits, it is considered an octal escape. Otherwise, it is a group reference. As for string literals, octal escapes are always at most -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 03:53:29 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 03:53:29 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314155=3A_merge_note_about_=5Cb_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/b1f29667a3c7 changeset: 76602:b1f29667a3c7 parent: 76599:bd195749c0a2 parent: 76601:f4b167309bee user: Ezio Melotti date: Sun Apr 29 04:53:20 2012 +0300 summary: #14155: merge note about \b from 3.2. files: Doc/library/re.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -417,6 +417,9 @@ \r \t \v \x \\ +(Note that ``\b`` is used to represent word boundaries, and means "backspace" +only inside character classes.) + Octal escapes are included in a limited form. If the first digit is a 0, or if there are three octal digits, it is considered an octal escape. Otherwise, it is a group reference. As for string literals, octal escapes are always at most -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 04:21:49 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 04:21:49 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_httplib_test_fo?= =?utf8?q?r_early_eof_response=2E_related_to_Issue13684?= Message-ID: http://hg.python.org/cpython/rev/685c1db976c4 changeset: 76603:685c1db976c4 branch: 2.7 parent: 76600:142297db28f1 user: Senthil Kumaran date: Sun Apr 29 10:15:31 2012 +0800 summary: httplib test for early eof response. related to Issue13684 files: Lib/test/test_httplib.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -349,6 +349,14 @@ resp.begin() self.assertRaises(httplib.LineTooLong, resp.read) + def test_early_eof(self): + # Test httpresponse with no \r\n termination, + body = "HTTP/1.1 200 Ok" + sock = FakeSocket(body) + resp = httplib.HTTPResponse(sock) + resp.begin() + self.assertEqual(resp.read(), '') + self.assertTrue(resp.isclosed()) class OfflineTest(TestCase): def test_responses(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 04:21:49 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 04:21:49 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_httplib_test_fo?= =?utf8?q?r_early_eof_response=2E_related_to_Issue13684?= Message-ID: http://hg.python.org/cpython/rev/afabb0635b15 changeset: 76604:afabb0635b15 branch: 3.2 parent: 76601:f4b167309bee user: Senthil Kumaran date: Sun Apr 29 10:20:46 2012 +0800 summary: httplib test for early eof response. related to Issue13684 files: Lib/test/test_httplib.py | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -369,6 +369,15 @@ resp.begin() self.assertRaises(client.LineTooLong, resp.read) + def test_early_eof(self): + # Test httpresponse with no \r\n termination, + body = "HTTP/1.1 200 Ok" + sock = FakeSocket(body) + resp = client.HTTPResponse(sock) + resp.begin() + self.assertEqual(resp.read(), b'') + self.assertTrue(resp.isclosed()) + class OfflineTest(TestCase): def test_responses(self): self.assertEqual(client.responses[client.NOT_FOUND], "Not Found") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 04:21:50 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 04:21:50 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_httplib_test_for_early_eof_response=2E_related_to_Issue13684?= Message-ID: http://hg.python.org/cpython/rev/cfff6a53f4a3 changeset: 76605:cfff6a53f4a3 parent: 76602:b1f29667a3c7 parent: 76604:afabb0635b15 user: Senthil Kumaran date: Sun Apr 29 10:21:26 2012 +0800 summary: httplib test for early eof response. related to Issue13684 files: Lib/test/test_httplib.py | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -489,6 +489,15 @@ resp.begin() self.assertRaises(client.LineTooLong, resp.read) + def test_early_eof(self): + # Test httpresponse with no \r\n termination, + body = "HTTP/1.1 200 Ok" + sock = FakeSocket(body) + resp = client.HTTPResponse(sock) + resp.begin() + self.assertEqual(resp.read(), b'') + self.assertTrue(resp.isclosed()) + class OfflineTest(TestCase): def test_responses(self): self.assertEqual(client.responses[client.NOT_FOUND], "Not Found") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 04:40:44 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 04:40:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_httplib_-_minor?= =?utf8?q?_update_to_check_empty_response?= Message-ID: http://hg.python.org/cpython/rev/1a9d38966395 changeset: 76606:1a9d38966395 branch: 3.2 parent: 76604:afabb0635b15 user: Senthil Kumaran date: Sun Apr 29 10:39:49 2012 +0800 summary: httplib - minor update to check empty response files: Lib/http/client.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/http/client.py b/Lib/http/client.py --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -563,7 +563,7 @@ # a vanishingly small number of sites EOF without # sending the trailer break - if line == b"\r\n": + if line in (b'\r\n', b'\n', b''): break # we read everything; close the "file" @@ -718,7 +718,7 @@ if not line: # for sites which EOF without sending a trailer break - if line == b'\r\n': + if line in (b'\r\n', b'\n', b''): break def connect(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 04:40:45 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 04:40:45 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_httplib_-_minor_update_to_check_empty_response?= Message-ID: http://hg.python.org/cpython/rev/6c227c1a80dd changeset: 76607:6c227c1a80dd parent: 76605:cfff6a53f4a3 parent: 76606:1a9d38966395 user: Senthil Kumaran date: Sun Apr 29 10:40:23 2012 +0800 summary: httplib - minor update to check empty response files: Lib/http/client.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/http/client.py b/Lib/http/client.py --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -557,7 +557,7 @@ # a vanishingly small number of sites EOF without # sending the trailer break - if line == b"\r\n": + if line in (b'\r\n', b'\n', b''): break def _readall_chunked(self): @@ -789,7 +789,7 @@ if not line: # for sites which EOF without sending a trailer break - if line == b'\r\n': + if line in (b'\r\n', b'\n', b''): break def connect(self): -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Apr 29 05:39:40 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 29 Apr 2012 05:39:40 +0200 Subject: [Python-checkins] Daily reference leaks (bd195749c0a2): sum=0 Message-ID: results for bd195749c0a2 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogw_wF_6', '-x'] From python-checkins at python.org Sun Apr 29 05:53:21 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 05:53:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_issue14427_-_Do?= =?utf8?q?cument_Request=2Eget=5Fheader_and_Request=2Eheader=5Fitems?= Message-ID: http://hg.python.org/cpython/rev/6a9f100e138c changeset: 76608:6a9f100e138c branch: 3.2 parent: 76606:1a9d38966395 user: Senthil Kumaran date: Sun Apr 29 11:50:39 2012 +0800 summary: issue14427 - Document Request.get_header and Request.header_items files: Doc/library/urllib.request.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -447,6 +447,17 @@ Return the selector --- the part of the URL that is sent to the server. +.. method:: Request.get_header(header_name, default=None) + + Return the value of the given header. If the header is not present, return + the default value. + + +.. method:: Request.header_items() + + Return a list of tuples (header_name, header_value) of the Request headers. + + .. method:: Request.set_proxy(host, type) Prepare the request by connecting to a proxy server. The *host* and *type* will -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 05:53:22 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 05:53:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_issue14427_-_Document_Request=2Eget=5Fheader_and_Request=2Eh?= =?utf8?q?eader=5Fitems?= Message-ID: http://hg.python.org/cpython/rev/261de1701343 changeset: 76609:261de1701343 parent: 76607:6c227c1a80dd parent: 76608:6a9f100e138c user: Senthil Kumaran date: Sun Apr 29 11:51:56 2012 +0800 summary: issue14427 - Document Request.get_header and Request.header_items files: Doc/library/urllib.request.rst | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -502,6 +502,18 @@ .. deprecated:: 3.3 +.. method:: Request.get_header(header_name, default=None) + + Return the value of the given header. If the header is not present, return + the default value. + + +.. method:: Request.header_items() + + Return a list of tuples (header_name, header_value) of the Request headers. + + +.. method:: Request.set_proxy(host, type) .. method:: Request.get_origin_req_host() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 05:53:23 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 05:53:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_issue14427_-_Do?= =?utf8?q?cument_Request=2Eget=5Fheader_and_Request=2Eheader=5Fitems?= Message-ID: http://hg.python.org/cpython/rev/9a1f525b98d9 changeset: 76610:9a1f525b98d9 branch: 2.7 parent: 76603:685c1db976c4 user: Senthil Kumaran date: Sun Apr 29 11:52:59 2012 +0800 summary: issue14427 - Document Request.get_header and Request.header_items files: Doc/library/urllib2.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/urllib2.rst b/Doc/library/urllib2.rst --- a/Doc/library/urllib2.rst +++ b/Doc/library/urllib2.rst @@ -380,6 +380,17 @@ Return the selector --- the part of the URL that is sent to the server. +.. method:: Request.get_header(header_name, default=None) + + Return the value of the given header. If the header is not present, return + the default value. + + +.. method:: Request.header_items() + + Return a list of tuples (header_name, header_value) of the Request headers. + + .. method:: Request.set_proxy(host, type) Prepare the request by connecting to a proxy server. The *host* and *type* will -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 06:35:38 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 06:35:38 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0NDYxOiBmaXgg?= =?utf8?q?wording=2E?= Message-ID: http://hg.python.org/cpython/rev/7c262962b681 changeset: 76611:7c262962b681 branch: 2.7 user: Ezio Melotti date: Sun Apr 29 07:34:22 2012 +0300 summary: #14461: fix wording. files: Doc/library/re.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -273,7 +273,7 @@ lookbehind will back up 3 characters and check if the contained pattern matches. The contained pattern must only match strings of some fixed length, meaning that ``abc`` or ``a|b`` are allowed, but ``a*`` and ``a{3,4}`` are not. Note that - patterns which start with positive lookbehind assertions will never match at the + patterns which start with positive lookbehind assertions will not match at the beginning of the string being searched; you will most likely want to use the :func:`search` function rather than the :func:`match` function: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 06:35:41 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 06:35:41 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NDYxOiBmaXgg?= =?utf8?q?wording=2E?= Message-ID: http://hg.python.org/cpython/rev/7f35da912739 changeset: 76612:7f35da912739 branch: 3.2 parent: 76608:6a9f100e138c user: Ezio Melotti date: Sun Apr 29 07:34:46 2012 +0300 summary: #14461: fix wording. files: Doc/library/re.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -278,7 +278,7 @@ lookbehind will back up 3 characters and check if the contained pattern matches. The contained pattern must only match strings of some fixed length, meaning that ``abc`` or ``a|b`` are allowed, but ``a*`` and ``a{3,4}`` are not. Note that - patterns which start with positive lookbehind assertions will never match at the + patterns which start with positive lookbehind assertions will not match at the beginning of the string being searched; you will most likely want to use the :func:`search` function rather than the :func:`match` function: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 06:35:42 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 06:35:42 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314461=3A_merge_with_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/d68b4885fc0f changeset: 76613:d68b4885fc0f parent: 76609:261de1701343 parent: 76612:7f35da912739 user: Ezio Melotti date: Sun Apr 29 07:35:22 2012 +0300 summary: #14461: merge with 3.2. files: Doc/library/re.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -278,7 +278,7 @@ lookbehind will back up 3 characters and check if the contained pattern matches. The contained pattern must only match strings of some fixed length, meaning that ``abc`` or ``a|b`` are allowed, but ``a*`` and ``a{3,4}`` are not. Note that - patterns which start with positive lookbehind assertions will never match at the + patterns which start with positive lookbehind assertions will not match at the beginning of the string being searched; you will most likely want to use the :func:`search` function rather than the :func:`match` function: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 06:52:17 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 06:52:17 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Fix_Issue6085_-_SimpleHTTPS?= =?utf8?q?erver_address=5Fstring_to_return_client_ip_instead_of?= Message-ID: http://hg.python.org/cpython/rev/64a6824d129d changeset: 76614:64a6824d129d user: Senthil Kumaran date: Sun Apr 29 12:51:54 2012 +0800 summary: Fix Issue6085 - SimpleHTTPServer address_string to return client ip instead of client hostname files: Doc/library/http.server.rst | 7 +++++-- Lib/http/server.py | 13 ++----------- Misc/NEWS | 3 +++ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -269,8 +269,11 @@ .. method:: address_string() - Returns the client address, formatted for logging. A name lookup is - performed on the client's IP address. + Returns the client address. + + .. versionchanged:: 3.3 + Previously, a name lookup was performed. To avoid name resolution + delays, it now always returns the IP address. .. class:: SimpleHTTPRequestHandler(request, client_address, server) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -558,15 +558,9 @@ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] def address_string(self): - """Return the client address formatted for logging. + """Return the client address.""" - This version looks up the full hostname using gethostbyaddr(), - and tries to find a name that contains at least one dot. - - """ - - host, port = self.client_address[:2] - return socket.getfqdn(host) + return self.client_address[0] # Essentially static class variables @@ -1040,9 +1034,6 @@ env['SCRIPT_NAME'] = scriptname if query: env['QUERY_STRING'] = query - host = self.address_string() - if host != self.client_address[0]: - env['REMOTE_HOST'] = host env['REMOTE_ADDR'] = self.client_address[0] authorization = self.headers.get("authorization") if authorization: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -81,6 +81,9 @@ Library ------- +- Issue #6085: In http.server.py SimpleHTTPServer.address_string returns the + client ip address instead client hostname. Patch by Charles-Fran?ois Natali. + - Issue #14309: Deprecate time.clock(), use time.perf_counter() or time.process_time() instead. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 07:24:10 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 07:24:10 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0MjM2OiBtZW50?= =?utf8?q?ion_Unicode_whitespace_in_=5Cs_documentation=2E?= Message-ID: http://hg.python.org/cpython/rev/da9179248118 changeset: 76615:da9179248118 branch: 3.2 parent: 76612:7f35da912739 user: Ezio Melotti date: Sun Apr 29 08:23:25 2012 +0300 summary: #14236: mention Unicode whitespace in \s documentation. files: Lib/re.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/re.py b/Lib/re.py --- a/Lib/re.py +++ b/Lib/re.py @@ -69,7 +69,10 @@ In string patterns without the ASCII flag, it will match the whole range of Unicode digits. \D Matches any non-digit character; equivalent to [^\d]. - \s Matches any whitespace character; equivalent to [ \t\n\r\f\v]. + \s Matches any whitespace character; equivalent to [ \t\n\r\f\v] in + bytes patterns or string patterns with the ASCII flag. + In string patterns without the ASCII flag, it will match the whole + range of Unicode whitespace characters. \S Matches any non-whitespace character; equiv. to [^ \t\n\r\f\v]. \w Matches any alphanumeric character; equivalent to [a-zA-Z0-9_] in bytes patterns or string patterns with the ASCII flag. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 07:24:11 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 07:24:11 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314236=3A_merge_with_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/db39b9513e71 changeset: 76616:db39b9513e71 parent: 76614:64a6824d129d parent: 76615:da9179248118 user: Ezio Melotti date: Sun Apr 29 08:24:02 2012 +0300 summary: #14236: merge with 3.2. files: Lib/re.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/re.py b/Lib/re.py --- a/Lib/re.py +++ b/Lib/re.py @@ -69,7 +69,10 @@ In string patterns without the ASCII flag, it will match the whole range of Unicode digits. \D Matches any non-digit character; equivalent to [^\d]. - \s Matches any whitespace character; equivalent to [ \t\n\r\f\v]. + \s Matches any whitespace character; equivalent to [ \t\n\r\f\v] in + bytes patterns or string patterns with the ASCII flag. + In string patterns without the ASCII flag, it will match the whole + range of Unicode whitespace characters. \S Matches any non-whitespace character; equiv. to [^ \t\n\r\f\v]. \w Matches any alphanumeric character; equivalent to [a-zA-Z0-9_] in bytes patterns or string patterns with the ASCII flag. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 07:39:03 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 07:39:03 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_=23119=3A_reorganize_the_t?= =?utf8?q?racker_documentation_in_the_devguide=2E?= Message-ID: http://hg.python.org/devguide/rev/252e2aabc87a changeset: 503:252e2aabc87a user: Ezio Melotti date: Sun Apr 29 08:37:40 2012 +0300 summary: #119: reorganize the tracker documentation in the devguide. files: devrole.rst | 24 ---- helptriage.rst | 63 ----------- index.rst | 8 +- languishing.rst | 26 ---- tracker.rst | 197 ++++++++++++++++++++++++++++++++++++ triaging.rst | 7 - 6 files changed, 199 insertions(+), 126 deletions(-) diff --git a/devrole.rst b/devrole.rst deleted file mode 100644 --- a/devrole.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. _devrole: - -Gaining the "Developer" Role on the Issue Tracker -================================================= - -When you have consistently shown the ability to properly -:ref:`help triage issues ` without guidance, you may request that you -be given the "Developer" role on the `issue tracker`_. You can make the request -of any person who already has the Developer role. If they decide you are ready -to gain the extra privileges on the tracker they will then act as a mentor to -you until you are ready to do things entirely on your own. There is no set rule -as to how many issues you need to have helped with before or how long you have -been participating. The key requirements are that you show the desire to -help, you are able to work well with others (especially those already with the -Developer role), and that have a firm grasp of how to do things on the issue -tracker properly on your own. - -Gaining the Developer role will allow you to set any value on any issue in the -tracker, releasing you from the burden of having to ask others to set values on -an issue for you in order to properly triage something. This will not only help -speed up and simplify your work in helping out, but also help lessen the -workload for everyone by gaining your help. - -.. _issue tracker: http://bugs.python.org diff --git a/helptriage.rst b/helptriage.rst deleted file mode 100644 --- a/helptriage.rst +++ /dev/null @@ -1,65 +0,0 @@ -.. _helptriage: - -Helping Triage Issues -===================== - -Once you know your way around how Python's source files are -structured and you are comfortable working with patches, a great way to -participate is to help triage issues. Do realize, though, that experience -working on Python is needed in order to effectively help triage. - -Around the clock, new issues are being opened on the `issue tracker`_ and -existing issues are being updated. Every -issue needs to be triaged to make sure various things are in proper order. Even -without special privileges you can help with this process. - - -Bugs ----- - -For bugs, an issue needs to: - -* clearly explain the bug so it can be reproduced -* include all relevant platform details -* state what version(s) of Python are affected by the bug. - -These are things you can help with once you have experience developing for -Python. For instance, if a bug is not clearly explained enough for you to -reproduce it then there is a good chance a core developer won't be able to -either. And it is always helpful to know if a bug not only affects the -in-development version of Python, but whether it also affects other versions in -maintenance mode. And if the bug lacks a unit test that should end up in -Python's test suite, having that written can be very helpful. - -This is all helpful as it allows triagers (i.e., -:ref:`people with the Developer role on the issue tracker `) to -properly classify an issue so it can be handled by the right core developers in -a timely fashion. - - -Patches -------- - -If an issue has a patch attached that has not been reviewed, you can help by -making sure the patch: - -* follows the style guides -* applies cleanly to an up-to-date checkout -* is a good solution to the problem it is trying to solve -* includes proper tests -* includes proper documentation changes -* submitter is listed in ``Misc/ACKS``, either already or the patch adds them - -Doing all of this allows core developers and :ref:`triagers ` to more -quickly look for subtle issues that only people with extensive experience -working on Python's code base will notice. - -There is a complete list of `open issues with patches`_ as well as a list of -`issues needing a review`_, although make sure -that someone has not already done the checklist above as it is possible the -issue is still open for reasons other than needing help being triaged. - - -.. _issue tracker: http://bugs.python.org -.. _issues needing a review: http://bugs.python.org/issue?status=1&@sort=-activity&@columns=id,activity,title,creator,status&@dispname=Show%20Needing%20Review&@startwith=0&@group=priority&@filter=&keywords=8&@action=search&@pagesize=50 -.. _open issues with patches: http://bugs.python.org/issue?status=1&@sort=-activity&@columns=id,activity,title,creator,status&@dispname=Issues%20with%20patch&@startwith=0&@group=priority&@filter=&keywords=2&@action=search&@pagesize=50 diff --git a/index.rst b/index.rst --- a/index.rst +++ b/index.rst @@ -13,10 +13,8 @@ documenting silencewarnings fixingissues - helptriage - devrole + tracker triaging - languishing communication coredev developers @@ -89,10 +87,8 @@ * :doc:`silencewarnings` * Fixing issues found by the :doc:`buildbots ` * :doc:`fixingissues` - * :doc:`helptriage` -* :doc:`devrole` +* :ref:`tracker` and :ref:`helptriage` * :doc:`triaging` - * :doc:`languishing` * :doc:`communication` * :doc:`coredev` * :doc:`committing` diff --git a/languishing.rst b/languishing.rst deleted file mode 100644 --- a/languishing.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _languishing: - -Marking Issues as "Languishing" -=============================== - -Sometimes an issue has no clear answer. It can be because core developers -cannot agree on the proper solution (or if a problem even exists). Other -times a solution is agreed upon but writing the code for the solution would -take too much effort for little gain, and so no one wants to do the work (or -would simply break too much pre-existing code without a different solution). - -In these cases an issue will languish_ in the `issue tracker`_, and its -status should be set as such. This -serves the purpose of preventing people who are trying to :ref:`fix issues -` from wasting time on issues that even core developers cannot -come up with an agreed-upon solution for. - -A good way to tell if an issue is languishing is based on whether it had -an in-depth discussion that stalled several months ago. In that instance it is -typically safe to set the status of the issue to "languishing". If you are -unsure you can always leave a comment on the issue asking if others agree that -it is languishing. - - -.. _issue tracker: http://bugs.python.org -.. _languish: http://bugs.python.org/issue?@columns=title,id,activity,status&@sort=activity&@group=priority&@filter=status&@pagesize=50&@startwith=0&status=4&@dispname=Languishing diff --git a/tracker.rst b/tracker.rst new file mode 100644 --- /dev/null +++ b/tracker.rst @@ -0,0 +1,197 @@ +.. _tracker: + +Using the Issue Tracker +======================= + +If you think you found a bug in Python, you can report it to the +`issue tracker`_. Documentation bugs can also be reported there. +Issues about the tracker should be reported to the `meta tracker`_. + + +Checking if a bug already exists +-------------------------------- + +The first step in filing a report is to determine whether the problem has +already been reported. The advantage in doing so, aside from saving the +developers time, is that you learn what has been done to fix it; it may be that +the problem has already been fixed for the next release, or additional +information is needed (in which case you are welcome to provide it if you can!). + +To do this, search the bug database using the search box on the top of the page. +An `advanced search`_ is also available by clicking on "Search" in +the sidebar. + + +Reporting an issue +------------------ + +If the problem you're reporting is not already in the `issue tracker`_, you +need to log in by entering your user and password in the form on the left. +If you don't already have a tracker account, select the "Register" link or, +if you use OpenID, one of the OpenID provider logos in the sidebar. + +It is not possible to submit a bug report anonymously. + +Being now logged in, you can submit a bug by clicking on the "Create New" link +in the sidebar. + +The submission form has a number of fields, and they are described in detail +in the :ref:`triaging` page. This is a short summary: + +* in the **Title** field, enter a *very* short description of the problem; + less than ten words is good; +* in the **Type** field, select the type of your problem (usually behavior); +* if you know which **Components** and **Versions** are affected by the issue, + you can select these too; +* if you have JavaScript enabled, you can use the **Nosy List** field to search + developers that can help with the issue by entering the name of the affected + module, operating system, or interest area. +* least but not last, you have to describe the problem in detail, including + what you expected to happen and what did happen, in the **Comment** field. + Be sure to include whether any extension modules were involved, and what + hardware and software platform you were using (including version information + as appropriate). + +The triaging team will take care of setting other fields, and possibly assign +the issue to a specific developer. You will automatically receive an update +each time an action is taken on the bug. + + +.. _helptriage: + +Helping Triage Issues +===================== + +Once you know your way around how Python's source files are +structured and you are comfortable working with patches, a great way to +participate is to help triage issues. Do realize, though, that experience +working on Python is needed in order to effectively help triage. + +Around the clock, new issues are being opened on the `issue tracker`_ and +existing issues are being updated. Every +issue needs to be triaged to make sure various things are in proper order. Even +without special privileges you can help with this process. + + +Classifying Reports +------------------- + +For bugs, an issue needs to: + +* clearly explain the bug so it can be reproduced +* include all relevant platform details +* state what version(s) of Python are affected by the bug. + +These are things you can help with once you have experience developing for +Python. For instance, if a bug is not clearly explained enough for you to +reproduce it then there is a good chance a core developer won't be able to +either. And it is always helpful to know if a bug not only affects the +in-development version of Python, but whether it also affects other versions in +maintenance mode. And if the bug lacks a unit test that should end up in +Python's test suite, having that written can be very helpful. + +This is all helpful as it allows triagers (i.e., +:ref:`people with the Developer role on the issue tracker `) to +properly classify an issue so it can be handled by the right core developers in +a timely fashion. + + +Reviewing Patches +----------------- + +If an issue has a patch attached that has not been reviewed, you can help by +making sure the patch: + +* follows the style guides +* applies cleanly to an up-to-date clone +* is a good solution to the problem it is trying to solve +* includes proper tests +* includes proper documentation changes +* submitter is listed in ``Misc/ACKS``, either already or the patch adds them + +Doing all of this allows core developers and :ref:`triagers ` to more +quickly look for subtle issues that only people with extensive experience +working on Python's code base will notice. + + +Finding an Issue You Can Help With +---------------------------------- + +If you want to help triaging issues, you might also want to search for issues +that you are knowledgeable about. An easy way to do it, is to search for +the name of a module you are familiar with. You can also use the +`advanced search`_ and search for specific components (e.g. "Windows" if you +are a Windows developer, "Extension Modules" if you are familiar with C, etc.). +Finally you can use the "Random issue" link in the sidebar to pick random +issues until you find an issue that you like. Is not so uncommon to find old +issues that can be closed, either because they are no longer valid, or +because they have a patch that is ready to be committed, but no one had +time to do it yet. + +In the sidebar you can also find links to summaries for easy issues and +issues with a patch. + + +.. _devrole: + +Gaining the "Developer" Role on the Issue Tracker +------------------------------------------------- + +When you have consistently shown the ability to properly +help triage issues without guidance, you may request that you +be given the "Developer" role on the `issue tracker`_. You can make the request +of any person who already has the Developer role. If they decide you are ready +to gain the extra privileges on the tracker they will then act as a mentor to +you until you are ready to do things entirely on your own. There is no set rule +as to how many issues you need to have helped with before or how long you have +been participating. The key requirements are that you show the desire to +help, you are able to work well with others (especially those already with the +Developer role), and that have a firm grasp of how to do things on the issue +tracker properly on your own. + +Gaining the Developer role will allow you to set any value on any issue in the +tracker, releasing you from the burden of having to ask others to set values on +an issue for you in order to properly triage something. This will not only help +speed up and simplify your work in helping out, but also help lessen the +workload for everyone by gaining your help. + + +The Meta Tracker +================ + +If you find an issue with the `issue tracker`_, you can report it to the +`meta tracker`_. The meta tracker is where you file issues against anything +you come across when working with the issue tracker itself (e.g you can't +attach a file, the layout is broken on your browser, Rietveld gave you an +error, etc.). + +If you want to contribute to the tracker you can get a checkout of the source +and install a local instance where to experiment. You can find detailed +instructions on the `Tracker Development`_ page. + + +.. seealso:: + + `The Python issue tracker `_ + Where to report issues about Python. + + `The New-bugs-announce mailing list `_ + Where all the new issues created on the tracker are reported. + + `The Python-bugs-list mailing list `_ + Where all the changes to issues are reported. + + `The meta tracker `_ + Where to report issues about the tracker itself. + + `The Tracker development wiki page `_ + Instructions about setting up a local instance of the bug tracker. + + `The Tracker-discuss mailing list `_ + Discussions about the bug tracker. + + +.. _issue tracker: http://bugs.python.org/ +.. _meta tracker: http://psf.upfronthosting.co.za/roundup/meta/ +.. _advanced search: http://bugs.python.org/issue?@template=search +.. _Tracker Development: http://wiki.python.org/moin/TrackerDevelopment diff --git a/triaging.rst b/triaging.rst --- a/triaging.rst +++ b/triaging.rst @@ -289,13 +289,6 @@ the Devguide, this page, and this section respectively. -Reporting Issues About the Tracker ----------------------------------- -The `meta tracker`_ is the tracker about the issue tracker. It is where you -file issues against anything you come across when working with the issue -tracker itself. - - .. _Doc: http://hg.python.org/cpython/file/default/Doc/ .. _Grammar: http://hg.python.org/cpython/file/default/Grammar/ .. _Lib: http://hg.python.org/cpython/file/default/Lib/ @@ -326,4 +319,3 @@ .. _Developer's guide: http://hg.python.org/devguide/ .. _GSoC: http://code.google.com/soc/ .. _issue tracker: http://bugs.python.org -.. _meta tracker: http://psf.upfronthosting.co.za/roundup/meta/ -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Apr 29 07:44:34 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 07:44:34 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Fix_issue6085_-?= =?utf8?q?_Remove_the_delay_caused_by_fqdn_lookup_while_logging_in?= Message-ID: http://hg.python.org/cpython/rev/fb1e71c7619a changeset: 76617:fb1e71c7619a branch: 2.7 parent: 76611:7c262962b681 user: Senthil Kumaran date: Sun Apr 29 13:39:16 2012 +0800 summary: Fix issue6085 - Remove the delay caused by fqdn lookup while logging in BaseHTTPRequestHandler files: Doc/library/basehttpserver.rst | 2 +- Lib/BaseHTTPServer.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/basehttpserver.rst b/Doc/library/basehttpserver.rst --- a/Doc/library/basehttpserver.rst +++ b/Doc/library/basehttpserver.rst @@ -240,7 +240,7 @@ to create custom error logging mechanisms. The *format* argument is a standard printf-style format string, where the additional arguments to :meth:`log_message` are applied as inputs to the formatting. The client - address and current date and time are prefixed to every message logged. + ip address and current date and time are prefixed to every message logged. .. method:: version_string() diff --git a/Lib/BaseHTTPServer.py b/Lib/BaseHTTPServer.py --- a/Lib/BaseHTTPServer.py +++ b/Lib/BaseHTTPServer.py @@ -447,13 +447,13 @@ specified as subsequent arguments (it's just like printf!). - The client host and current date/time are prefixed to - every message. + The client ip address and current date/time are prefixed to every + message. """ sys.stderr.write("%s - - [%s] %s\n" % - (self.address_string(), + (self.client_address[0], self.log_date_time_string(), format%args)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 07:44:35 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 07:44:35 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Fix_issue6085_-?= =?utf8?q?_Remove_the_delay_caused_by_fqdn_lookup_while_logging_in?= Message-ID: http://hg.python.org/cpython/rev/6adad27fcc8c changeset: 76618:6adad27fcc8c branch: 3.2 parent: 76615:da9179248118 user: Senthil Kumaran date: Sun Apr 29 13:41:03 2012 +0800 summary: Fix issue6085 - Remove the delay caused by fqdn lookup while logging in BaseHTTPRequestHandler files: Doc/library/http.server.rst | 2 +- Lib/http/server.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -229,7 +229,7 @@ to create custom error logging mechanisms. The *format* argument is a standard printf-style format string, where the additional arguments to :meth:`log_message` are applied as inputs to the formatting. The client - address and current date and time are prefixed to every message logged. + ip address and current date and time are prefixed to every message logged. .. method:: version_string() diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -508,13 +508,13 @@ specified as subsequent arguments (it's just like printf!). - The client host and current date/time are prefixed to + The client ip and current date/time are prefixed to every message. """ sys.stderr.write("%s - - [%s] %s\n" % - (self.address_string(), + (self.client_address[0], self.log_date_time_string(), format%args)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 07:44:36 2012 From: python-checkins at python.org (senthil.kumaran) Date: Sun, 29 Apr 2012 07:44:36 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_issue6085_-_update_docs_in_default_branch?= Message-ID: http://hg.python.org/cpython/rev/f9f11998a20d changeset: 76619:f9f11998a20d parent: 76616:db39b9513e71 parent: 76618:6adad27fcc8c user: Senthil Kumaran date: Sun Apr 29 13:44:14 2012 +0800 summary: issue6085 - update docs in default branch files: Doc/library/http.server.rst | 2 +- Lib/http/server.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -248,7 +248,7 @@ to create custom error logging mechanisms. The *format* argument is a standard printf-style format string, where the additional arguments to :meth:`log_message` are applied as inputs to the formatting. The client - address and current date and time are prefixed to every message logged. + ip address and current date and time are prefixed to every message logged. .. method:: version_string() diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -518,7 +518,7 @@ specified as subsequent arguments (it's just like printf!). - The client host and current date/time are prefixed to + The client ip and current date/time are prefixed to every message. """ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 09:53:39 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 09:53:39 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Fix_markup_in_u?= =?utf8?q?nittest_doc=2E?= Message-ID: http://hg.python.org/cpython/rev/de64931637cd changeset: 76620:de64931637cd branch: 2.7 parent: 76617:fb1e71c7619a user: Ezio Melotti date: Sun Apr 29 10:52:18 2012 +0300 summary: Fix markup in unittest doc. files: Doc/library/unittest.rst | 4 ++-- 1 files changed, 2 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 @@ -1426,8 +1426,8 @@ The :class:`TestLoader` class is used to create test suites from classes and modules. Normally, there is no need to create an instance of this class; the :mod:`unittest` module provides an instance that can be shared as - ``unittest.defaultTestLoader``. Using a subclass or instance, however, allows - customization of some configurable properties. + :data:`unittest.defaultTestLoader`. Using a subclass or instance, however, + allows customization of some configurable properties. :class:`TestLoader` objects have the following methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 09:53:40 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 09:53:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Fix_markup_in_u?= =?utf8?q?nittest_doc=2E?= Message-ID: http://hg.python.org/cpython/rev/2620641725bb changeset: 76621:2620641725bb branch: 3.2 parent: 76618:6adad27fcc8c user: Ezio Melotti date: Sun Apr 29 10:52:18 2012 +0300 summary: Fix markup in unittest doc. files: Doc/library/unittest.rst | 4 ++-- 1 files changed, 2 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 @@ -1553,8 +1553,8 @@ The :class:`TestLoader` class is used to create test suites from classes and modules. Normally, there is no need to create an instance of this class; the :mod:`unittest` module provides an instance that can be shared as - ``unittest.defaultTestLoader``. Using a subclass or instance, however, allows - customization of some configurable properties. + :data:`unittest.defaultTestLoader`. Using a subclass or instance, however, + allows customization of some configurable properties. :class:`TestLoader` objects have the following methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 09:53:40 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 09:53:40 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_markup_fix_in_unittest_doc_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/653f79e357f8 changeset: 76622:653f79e357f8 parent: 76619:f9f11998a20d parent: 76621:2620641725bb user: Ezio Melotti date: Sun Apr 29 10:53:31 2012 +0300 summary: Merge markup fix in unittest doc from 3.2. files: Doc/library/unittest.rst | 4 ++-- 1 files changed, 2 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 @@ -1547,8 +1547,8 @@ The :class:`TestLoader` class is used to create test suites from classes and modules. Normally, there is no need to create an instance of this class; the :mod:`unittest` module provides an instance that can be shared as - ``unittest.defaultTestLoader``. Using a subclass or instance, however, allows - customization of some configurable properties. + :data:`unittest.defaultTestLoader`. Using a subclass or instance, however, + allows customization of some configurable properties. :class:`TestLoader` objects have the following methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 09:59:01 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 29 Apr 2012 09:59:01 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Better_control_when_dumping?= =?utf8?q?_import_state?= Message-ID: http://hg.python.org/cpython/rev/00221c8b7c86 changeset: 76623:00221c8b7c86 user: Nick Coghlan date: Sun Apr 29 17:58:24 2012 +1000 summary: Better control when dumping import state files: Tools/scripts/import_diagnostics.py | 22 +++++++--------- 1 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Tools/scripts/import_diagnostics.py b/Tools/scripts/import_diagnostics.py --- a/Tools/scripts/import_diagnostics.py +++ b/Tools/scripts/import_diagnostics.py @@ -7,27 +7,25 @@ def _dump_state(args): print(sys.version) - print("sys.path:") - pprint(sys.path) - print("sys.meta_path") - pprint(sys.meta_path) - print("sys.path_hooks") - pprint(sys.path_hooks) - print("sys.path_importer_cache") - pprint(sys.path_importer_cache) - print("sys.modules:") - pprint(sys.modules) + for name in args.attributes: + print("sys.{}:".format(name)) + pprint(getattr(sys, name)) + +def _add_dump_args(cmd): + cmd.add_argument("attributes", metavar="ATTR", nargs="+", + help="sys module attribute to display") COMMANDS = ( - ("dump", "Dump import state", _dump_state), + ("dump", "Dump import state", _dump_state, _add_dump_args), ) def _make_parser(): parser = argparse.ArgumentParser() sub = parser.add_subparsers(title="Commands") - for name, description, implementation in COMMANDS: + for name, description, implementation, add_args in COMMANDS: cmd = sub.add_parser(name, help=description) cmd.set_defaults(command=implementation) + add_args(cmd) return parser def main(args): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 10:49:02 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 10:49:02 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0NTE5OiBmaXgg?= =?utf8?q?the_regex_used_in_the_scanf_example=2E?= Message-ID: http://hg.python.org/cpython/rev/b26471a2a115 changeset: 76624:b26471a2a115 branch: 2.7 parent: 76620:de64931637cd user: Ezio Melotti date: Sun Apr 29 11:47:28 2012 +0300 summary: #14519: fix the regex used in the scanf example. files: Doc/library/re.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -1058,13 +1058,13 @@ +--------------------------------+---------------------------------------------+ | ``%i`` | ``[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)`` | +--------------------------------+---------------------------------------------+ -| ``%o`` | ``0[0-7]*`` | +| ``%o`` | ``[-+]?[0-7]+`` | +--------------------------------+---------------------------------------------+ | ``%s`` | ``\S+`` | +--------------------------------+---------------------------------------------+ | ``%u`` | ``\d+`` | +--------------------------------+---------------------------------------------+ -| ``%x``, ``%X`` | ``0[xX][\dA-Fa-f]+`` | +| ``%x``, ``%X`` | ``[-+]?(0[xX])?[\dA-Fa-f]+`` | +--------------------------------+---------------------------------------------+ To extract the filename and numbers from a string like :: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 10:49:03 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 10:49:03 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NTE5OiBmaXgg?= =?utf8?q?the_regex_used_in_the_scanf_example=2E?= Message-ID: http://hg.python.org/cpython/rev/e317d651ccf8 changeset: 76625:e317d651ccf8 branch: 3.2 parent: 76621:2620641725bb user: Ezio Melotti date: Sun Apr 29 11:47:28 2012 +0300 summary: #14519: fix the regex used in the scanf example. files: Doc/library/re.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -1072,13 +1072,13 @@ +--------------------------------+---------------------------------------------+ | ``%i`` | ``[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)`` | +--------------------------------+---------------------------------------------+ -| ``%o`` | ``0[0-7]*`` | +| ``%o`` | ``[-+]?[0-7]+`` | +--------------------------------+---------------------------------------------+ | ``%s`` | ``\S+`` | +--------------------------------+---------------------------------------------+ | ``%u`` | ``\d+`` | +--------------------------------+---------------------------------------------+ -| ``%x``, ``%X`` | ``0[xX][\dA-Fa-f]+`` | +| ``%x``, ``%X`` | ``[-+]?(0[xX])?[\dA-Fa-f]+`` | +--------------------------------+---------------------------------------------+ To extract the filename and numbers from a string like :: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 10:49:04 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 10:49:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314519=3A_merge_with_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/7cc1cddb378d changeset: 76626:7cc1cddb378d parent: 76623:00221c8b7c86 parent: 76625:e317d651ccf8 user: Ezio Melotti date: Sun Apr 29 11:48:54 2012 +0300 summary: #14519: merge with 3.2. files: Doc/library/re.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -1075,13 +1075,13 @@ +--------------------------------+---------------------------------------------+ | ``%i`` | ``[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)`` | +--------------------------------+---------------------------------------------+ -| ``%o`` | ``0[0-7]*`` | +| ``%o`` | ``[-+]?[0-7]+`` | +--------------------------------+---------------------------------------------+ | ``%s`` | ``\S+`` | +--------------------------------+---------------------------------------------+ | ``%u`` | ``\d+`` | +--------------------------------+---------------------------------------------+ -| ``%x``, ``%X`` | ``0[xX][\dA-Fa-f]+`` | +| ``%x``, ``%X`` | ``[-+]?(0[xX])?[\dA-Fa-f]+`` | +--------------------------------+---------------------------------------------+ To extract the filename and numbers from a string like :: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 11:58:25 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 11:58:25 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_Reorder_sections_in_the_he?= =?utf8?q?lp_page=2E?= Message-ID: http://hg.python.org/devguide/rev/ebb84bd3e3f8 changeset: 504:ebb84bd3e3f8 user: Ezio Melotti date: Sun Apr 29 12:58:16 2012 +0300 summary: Reorder sections in the help page. files: help.rst | 34 ++++++++++++++++++---------------- 1 files changed, 18 insertions(+), 16 deletions(-) diff --git a/help.rst b/help.rst --- a/help.rst +++ b/help.rst @@ -26,17 +26,17 @@ .. _freenode: http://freenode.net/ -File a Bug ----------- +Core Mentorship +--------------- -If you strongly suspect you have stumbled on a bug (be it in the build -process, in the test suite, or in other areas), then open an issue on the -`issue tracker`_. As with every bug report it is strongly advised that -you detail which conditions triggered it (including the OS name and version, -and what you were trying to do), as well as the exact error message you -encountered. +If you are interested in improving Python and contributing to its development, +but don?t yet feel entirely comfortable with the public channels mentioned +above, `Python Mentors`_ are here to help you. Python is fortunate to have a +community of volunteer core developers willing to mentor anyone wishing to +contribute code, work on bug fixes or improve documentation. Everyone is +welcomed and encouraged to contribute. -.. _issue tracker: http://bugs.python.org +.. _Python Mentors: http://pythonmentors.com Mailing Lists @@ -56,14 +56,14 @@ .. _python-dev: http://mail.python.org/mailman/listinfo/python-dev -Core Mentorship ---------------- +File a Bug +---------- -If you are interested in improving Python and contributing to its development, -but don?t yet feel entirely comfortable with the public channels mentioned -above, `Python Mentors`_ are here to help you. Python is fortunate to have a -community of volunteer core developers willing to mentor anyone wishing to -contribute code, work on bug fixes or improve documentation. Everyone is -welcomed and encouraged to contribute. +If you strongly suspect you have stumbled on a bug (be it in the build +process, in the test suite, or in other areas), then open an issue on the +`issue tracker`_. As with every bug report it is strongly advised that +you detail which conditions triggered it (including the OS name and version, +and what you were trying to do), as well as the exact error message you +encountered. -.. _Python Mentors: http://pythonmentors.com +.. _issue tracker: http://bugs.python.org -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Apr 29 12:22:12 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 12:22:12 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_Move_the_devrole_section_o?= =?utf8?q?ne_level_up=2E?= Message-ID: http://hg.python.org/devguide/rev/666105c412d8 changeset: 505:666105c412d8 user: Ezio Melotti date: Sun Apr 29 13:21:57 2012 +0300 summary: Move the devrole section one level up. files: tracker.rst | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/tracker.rst b/tracker.rst --- a/tracker.rst +++ b/tracker.rst @@ -135,7 +135,7 @@ .. _devrole: Gaining the "Developer" Role on the Issue Tracker -------------------------------------------------- +================================================= When you have consistently shown the ability to properly help triage issues without guidance, you may request that you -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Apr 29 12:37:25 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 12:37:25 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0MjM2OiBmaXgg?= =?utf8?q?docs_for_=5CS=2E?= Message-ID: http://hg.python.org/cpython/rev/23d5b457dc71 changeset: 76627:23d5b457dc71 branch: 3.2 parent: 76625:e317d651ccf8 user: Ezio Melotti date: Sun Apr 29 13:35:55 2012 +0300 summary: #14236: fix docs for \S. files: Lib/re.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/re.py b/Lib/re.py --- a/Lib/re.py +++ b/Lib/re.py @@ -73,7 +73,7 @@ bytes patterns or string patterns with the ASCII flag. In string patterns without the ASCII flag, it will match the whole range of Unicode whitespace characters. - \S Matches any non-whitespace character; equiv. to [^ \t\n\r\f\v]. + \S Matches any non-whitespace character; equivalent to [^\s]. \w Matches any alphanumeric character; equivalent to [a-zA-Z0-9_] in bytes patterns or string patterns with the ASCII flag. In string patterns without the ASCII flag, it will match the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 12:37:26 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 29 Apr 2012 12:37:26 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314236=3A_merge_with_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/9165774a8055 changeset: 76628:9165774a8055 parent: 76626:7cc1cddb378d parent: 76627:23d5b457dc71 user: Ezio Melotti date: Sun Apr 29 13:37:13 2012 +0300 summary: #14236: merge with 3.2. files: Lib/re.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/re.py b/Lib/re.py --- a/Lib/re.py +++ b/Lib/re.py @@ -73,7 +73,7 @@ bytes patterns or string patterns with the ASCII flag. In string patterns without the ASCII flag, it will match the whole range of Unicode whitespace characters. - \S Matches any non-whitespace character; equiv. to [^ \t\n\r\f\v]. + \S Matches any non-whitespace character; equivalent to [^\s]. \w Matches any alphanumeric character; equivalent to [a-zA-Z0-9_] in bytes patterns or string patterns with the ASCII flag. In string patterns without the ASCII flag, it will match the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 16:32:04 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Apr 2012 16:32:04 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314521=3A_Make_resu?= =?utf8?q?lt_of_float=28=27nan=27=29_and_float=28=27-nan=27=29_more_consis?= =?utf8?q?tent?= Message-ID: http://hg.python.org/cpython/rev/c468511fc887 changeset: 76629:c468511fc887 user: Mark Dickinson date: Sun Apr 29 15:31:56 2012 +0100 summary: Issue #14521: Make result of float('nan') and float('-nan') more consistent across platforms. Further, don't rely on Py_HUGE_VAL for float('inf'). files: Include/dtoa.h | 2 + Lib/test/test_float.py | 13 +++++++ Misc/NEWS | 3 + Python/dtoa.c | 50 +++++++++++++++++++++++++++--- Python/pystrtod.c | 39 +++++++++++++++++++++++ 5 files changed, 102 insertions(+), 5 deletions(-) diff --git a/Include/dtoa.h b/Include/dtoa.h --- a/Include/dtoa.h +++ b/Include/dtoa.h @@ -8,6 +8,8 @@ PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve); PyAPI_FUNC(void) _Py_dg_freedtoa(char *s); +PyAPI_FUNC(double) _Py_dg_stdnan(int sign); +PyAPI_FUNC(double) _Py_dg_infinity(int sign); #ifdef __cplusplus diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -870,6 +870,19 @@ self.assertFalse(NAN.is_inf()) self.assertFalse((0.).is_inf()) + def test_inf_signs(self): + self.assertEqual(copysign(1.0, float('inf')), 1.0) + self.assertEqual(copysign(1.0, float('-inf')), -1.0) + + @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', + "applies only when using short float repr style") + def test_nan_signs(self): + # When using the dtoa.c code, the sign of float('nan') should + # be predictable. + self.assertEqual(copysign(1.0, float('nan')), 1.0) + self.assertEqual(copysign(1.0, float('-nan')), -1.0) + + fromHex = float.fromhex toHex = float.hex class HexFloatTestCase(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14521: Make result of float('nan') and float('-nan') more + consistent across platforms. + - Issue #14646: __import__() sets __loader__ if the loader did not. - Issue #14605: No longer have implicit entries in sys.meta_path. If diff --git a/Python/dtoa.c b/Python/dtoa.c --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -265,6 +265,16 @@ #define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) #define Big1 0xffffffff +/* Standard NaN used by _Py_dg_stdnan. */ + +#define NAN_WORD0 0x7ff80000 +#define NAN_WORD1 0 + +/* Bits of the representation of positive infinity. */ + +#define POSINF_WORD0 0x7ff00000 +#define POSINF_WORD1 0 + /* struct BCinfo is used to pass information from _Py_dg_strtod to bigcomp */ typedef struct BCinfo BCinfo; @@ -1486,6 +1496,36 @@ return 0; } +/* Return a 'standard' NaN value. + + There are exactly two quiet NaNs that don't arise by 'quieting' signaling + NaNs (see IEEE 754-2008, section 6.2.1). If sign == 0, return the one whose + sign bit is cleared. Otherwise, return the one whose sign bit is set. +*/ + +double +_Py_dg_stdnan(int sign) +{ + U rv; + word0(&rv) = NAN_WORD0; + word1(&rv) = NAN_WORD1; + if (sign) + word0(&rv) |= Sign_bit; + return dval(&rv); +} + +/* Return positive or negative infinity, according to the given sign (0 for + * positive infinity, 1 for negative infinity). */ + +double +_Py_dg_infinity(int sign) +{ + U rv; + word0(&rv) = POSINF_WORD0; + word1(&rv) = POSINF_WORD1; + return sign ? -dval(&rv) : dval(&rv); +} + double _Py_dg_strtod(const char *s00, char **se) { @@ -1886,20 +1926,20 @@ bd2++; /* At this stage bd5 - bb5 == e == bd2 - bb2 + bbe, bb2 - bs2 == 1, - and bs == 1, so: + and bs == 1, so: tdv == bd * 10**e = bd * 2**(bbe - bb2 + bd2) * 5**(bd5 - bb5) srv == bb * 2**bbe = bb * 2**(bbe - bb2 + bb2) - 0.5 ulp(srv) == 2**(bbe-1) = bs * 2**(bbe - bb2 + bs2) + 0.5 ulp(srv) == 2**(bbe-1) = bs * 2**(bbe - bb2 + bs2) - It follows that: + It follows that: M * tdv = bd * 2**bd2 * 5**bd5 M * srv = bb * 2**bb2 * 5**bb5 M * 0.5 ulp(srv) = bs * 2**bs2 * 5**bb5 - for some constant M. (Actually, M == 2**(bb2 - bbe) * 5**bb5, but - this fact is not needed below.) + for some constant M. (Actually, M == 2**(bb2 - bbe) * 5**bb5, but + this fact is not needed below.) */ /* Remove factor of 2**i, where i = min(bb2, bd2, bs2). */ diff --git a/Python/pystrtod.c b/Python/pystrtod.c --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -22,6 +22,43 @@ the successfully parsed portion of the string. On failure, return -1.0 and set *endptr to point to the start of the string. */ +#ifndef PY_NO_SHORT_FLOAT_REPR + +double +_Py_parse_inf_or_nan(const char *p, char **endptr) +{ + double retval; + const char *s; + int negate = 0; + + s = p; + if (*s == '-') { + negate = 1; + s++; + } + else if (*s == '+') { + s++; + } + if (case_insensitive_match(s, "inf")) { + s += 3; + if (case_insensitive_match(s, "inity")) + s += 5; + retval = _Py_dg_infinity(negate); + } + else if (case_insensitive_match(s, "nan")) { + s += 3; + retval = _Py_dg_stdnan(negate); + } + else { + s = p; + retval = -1.0; + } + *endptr = (char *)s; + return retval; +} + +#else + double _Py_parse_inf_or_nan(const char *p, char **endptr) { @@ -57,6 +94,8 @@ return retval; } +#endif + /** * _PyOS_ascii_strtod: * @nptr: the string to convert to a numeric value. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 17:12:46 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Apr 2012 17:12:46 +0200 Subject: [Python-checkins] =?utf8?q?devguide=3A_Record_Richard_Oudkerk=2E?= Message-ID: http://hg.python.org/devguide/rev/da272d76e9fc changeset: 506:da272d76e9fc user: Antoine Pitrou date: Sun Apr 29 17:11:11 2012 +0200 summary: Record Richard Oudkerk. files: developers.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/developers.rst b/developers.rst --- a/developers.rst +++ b/developers.rst @@ -24,6 +24,11 @@ Permissions History ------------------- +- Richard Oudkerk was given push privileges on Apr 29 2012 by Antoine Pitrou + on recommendation by Charles-Fran?ois Natali and Jesse Noller, for various + contributions to multiprocessing (and original authorship of + multiprocessing's predecessor, the processing package). + - Andrew Svetlov was given push privileges on Mar 13 2012 by MvL at the PyCon sprint. -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Apr 29 18:25:44 2012 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 29 Apr 2012 18:25:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=282=2E7=29=3A_Fix_typo?= Message-ID: http://hg.python.org/cpython/rev/5bad73fbf593 changeset: 76630:5bad73fbf593 branch: 2.7 parent: 76624:b26471a2a115 user: Raymond Hettinger date: Sun Apr 29 09:25:25 2012 -0700 summary: Fix typo files: Doc/howto/sorting.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/howto/sorting.rst b/Doc/howto/sorting.rst --- a/Doc/howto/sorting.rst +++ b/Doc/howto/sorting.rst @@ -124,7 +124,7 @@ ======================== Both :meth:`list.sort` and :func:`sorted` accept a *reverse* parameter with a -boolean value. This is using to flag descending sorts. For example, to get the +boolean value. This is used to flag descending sorts. For example, to get the student data in reverse *age* order: >>> sorted(student_tuples, key=itemgetter(2), reverse=True) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 18:36:07 2012 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 29 Apr 2012 18:36:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Issue_14688=3A_?= =?utf8?q?Fix_typo?= Message-ID: http://hg.python.org/cpython/rev/295fec2cd5ed changeset: 76631:295fec2cd5ed branch: 3.2 parent: 76627:23d5b457dc71 user: Raymond Hettinger date: Sun Apr 29 09:32:30 2012 -0700 summary: Issue 14688: Fix typo files: Doc/howto/sorting.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/howto/sorting.rst b/Doc/howto/sorting.rst --- a/Doc/howto/sorting.rst +++ b/Doc/howto/sorting.rst @@ -42,7 +42,7 @@ Key Functions ============= -Both :meth:`list.sort` and :func:`sorted` have *key* parameter to specify a +Both :meth:`list.sort` and :func:`sorted` have a *key* parameter to specify a function to be called on each list element prior to making comparisons. For example, here's a case-insensitive string comparison: @@ -89,7 +89,7 @@ The key-function patterns shown above are very common, so Python provides convenience functions to make accessor functions easier and faster. The :mod:`operator` module has :func:`~operator.itemgetter`, -:func:`~operator.attrgetter`, and an :func:`~operator.methodcaller` function. +:func:`~operator.attrgetter`, and a :func:`~operator.methodcaller` function. Using those functions, the above examples become simpler and faster: @@ -114,7 +114,7 @@ ======================== Both :meth:`list.sort` and :func:`sorted` accept a *reverse* parameter with a -boolean value. This is using to flag descending sorts. For example, to get the +boolean value. This is used to flag descending sorts. For example, to get the student data in reverse *age* order: >>> sorted(student_tuples, key=itemgetter(2), reverse=True) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 18:36:08 2012 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 29 Apr 2012 18:36:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/16635c81b329 changeset: 76632:16635c81b329 parent: 76629:c468511fc887 user: Raymond Hettinger date: Sun Apr 29 09:35:39 2012 -0700 summary: merge files: Doc/howto/sorting.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/howto/sorting.rst b/Doc/howto/sorting.rst --- a/Doc/howto/sorting.rst +++ b/Doc/howto/sorting.rst @@ -42,7 +42,7 @@ Key Functions ============= -Both :meth:`list.sort` and :func:`sorted` have *key* parameter to specify a +Both :meth:`list.sort` and :func:`sorted` have a *key* parameter to specify a function to be called on each list element prior to making comparisons. For example, here's a case-insensitive string comparison: @@ -89,7 +89,7 @@ The key-function patterns shown above are very common, so Python provides convenience functions to make accessor functions easier and faster. The :mod:`operator` module has :func:`~operator.itemgetter`, -:func:`~operator.attrgetter`, and an :func:`~operator.methodcaller` function. +:func:`~operator.attrgetter`, and a :func:`~operator.methodcaller` function. Using those functions, the above examples become simpler and faster: @@ -114,7 +114,7 @@ ======================== Both :meth:`list.sort` and :func:`sorted` accept a *reverse* parameter with a -boolean value. This is using to flag descending sorts. For example, to get the +boolean value. This is used to flag descending sorts. For example, to get the student data in reverse *age* order: >>> sorted(student_tuples, key=itemgetter(2), reverse=True) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 18:50:37 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 29 Apr 2012 18:50:37 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2313959=3A_Re-implem?= =?utf8?q?ent_imp=2ENullImporter_in_Lib/imp=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/eb5c5c23ca9b changeset: 76633:eb5c5c23ca9b parent: 76629:c468511fc887 user: Brett Cannon date: Sun Apr 29 12:50:03 2012 -0400 summary: Issue #13959: Re-implement imp.NullImporter in Lib/imp.py. files: Lib/imp.py | 17 +++- Lib/test/test_sys.py | 3 - Python/import.c | 141 +------------------------------ 3 files changed, 17 insertions(+), 144 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -14,8 +14,6 @@ from _imp import get_magic, get_tag # Can (probably) move to importlib from _imp import get_suffixes -# Should be re-implemented here (and mostly deprecated) -from _imp import NullImporter from importlib._bootstrap import _new_module as new_module from importlib._bootstrap import _cache_from_source as cache_from_source @@ -60,6 +58,21 @@ return os.path.join(head, base_filename + _bootstrap.SOURCE_SUFFIXES[0]) +class NullImporter: + + """Null import object.""" + + def __init__(self, path): + if path == '': + raise ImportError('empty pathname', path='') + elif os.path.isdir(path): + raise ImportError('existing directory', path=path) + + def find_module(self, fullname): + """Always returns None.""" + return None + + class _HackedGetData: """Compatibiilty support for 'file' arguments of various load_*() diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -889,9 +889,6 @@ # _ast.AST import _ast check(_ast.AST(), size(h + 'P')) - # imp.NullImporter - import imp - check(imp.NullImporter(self.file.name), size(h + '')) try: raise TypeError except TypeError: diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -205,9 +205,6 @@ PyObject *v, *path_hooks = NULL; int err = 0; - if (PyType_Ready(&PyNullImporter_Type) < 0) - goto error; - /* adding sys.path_hooks and sys.path_importer_cache */ v = PyList_New(0); if (v == NULL) @@ -231,8 +228,7 @@ error: PyErr_Print(); Py_FatalError("initializing sys.meta_path, sys.path_hooks, " - "path_importer_cache, or NullImporter failed" - ); + "or path_importer_cache"); } Py_DECREF(path_hooks); } @@ -284,7 +280,7 @@ error: PyErr_Print(); - Py_FatalError("initializing zipimport or NullImporter failed"); + Py_FatalError("initializing zipimport failed"); } /* Locking primitives to prevent parallel imports of the same module @@ -2244,134 +2240,6 @@ return err; } -typedef struct { - PyObject_HEAD -} NullImporter; - -static int -NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) -{ -#ifndef MS_WINDOWS - PyObject *path; - struct stat statbuf; - int rv; - - if (!_PyArg_NoKeywords("NullImporter()", kwds)) - return -1; - - if (!PyArg_ParseTuple(args, "O&:NullImporter", - PyUnicode_FSConverter, &path)) - return -1; - - if (PyBytes_GET_SIZE(path) == 0) { - Py_DECREF(path); - PyErr_SetString(PyExc_ImportError, "empty pathname"); - return -1; - } - - rv = stat(PyBytes_AS_STRING(path), &statbuf); - Py_DECREF(path); - if (rv == 0) { - /* it exists */ - if (S_ISDIR(statbuf.st_mode)) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, "existing directory"); - return -1; - } - } -#else /* MS_WINDOWS */ - PyObject *pathobj; - DWORD rv; - wchar_t *path; - - if (!_PyArg_NoKeywords("NullImporter()", kwds)) - return -1; - - if (!PyArg_ParseTuple(args, "U:NullImporter", - &pathobj)) - return -1; - - if (PyUnicode_GET_LENGTH(pathobj) == 0) { - PyErr_SetString(PyExc_ImportError, "empty pathname"); - return -1; - } - - path = PyUnicode_AsWideCharString(pathobj, NULL); - if (path == NULL) - return -1; - /* see issue1293 and issue3677: - * stat() on Windows doesn't recognise paths like - * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. - */ - rv = GetFileAttributesW(path); - PyMem_Free(path); - if (rv != INVALID_FILE_ATTRIBUTES) { - /* it exists */ - if (rv & FILE_ATTRIBUTE_DIRECTORY) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, "existing directory"); - return -1; - } - } -#endif - return 0; -} - -static PyObject * -NullImporter_find_module(NullImporter *self, PyObject *args) -{ - Py_RETURN_NONE; -} - -static PyMethodDef NullImporter_methods[] = { - {"find_module", (PyCFunction)NullImporter_find_module, METH_VARARGS, - "Always return None" - }, - {NULL} /* Sentinel */ -}; - - -PyTypeObject PyNullImporter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "imp.NullImporter", /*tp_name*/ - sizeof(NullImporter), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*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*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Null importer object", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - NullImporter_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 */ - (initproc)NullImporter_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew /* tp_new */ -}; - static struct PyModuleDef impmodule = { PyModuleDef_HEAD_INIT, "_imp", @@ -2389,9 +2257,6 @@ { PyObject *m, *d; - if (PyType_Ready(&PyNullImporter_Type) < 0) - return NULL; - m = PyModule_Create(&impmodule); if (m == NULL) goto failure; @@ -2410,8 +2275,6 @@ if (setint(d, "PY_CODERESOURCE", PY_CODERESOURCE) < 0) goto failure; if (setint(d, "IMP_HOOK", IMP_HOOK) < 0) goto failure; - Py_INCREF(&PyNullImporter_Type); - PyModule_AddObject(m, "NullImporter", (PyObject *)&PyNullImporter_Type); return m; failure: Py_XDECREF(m); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 18:50:38 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 29 Apr 2012 18:50:38 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/534cbebd7a71 changeset: 76634:534cbebd7a71 parent: 76633:eb5c5c23ca9b parent: 76632:16635c81b329 user: Brett Cannon date: Sun Apr 29 12:50:32 2012 -0400 summary: merge files: Doc/howto/sorting.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/howto/sorting.rst b/Doc/howto/sorting.rst --- a/Doc/howto/sorting.rst +++ b/Doc/howto/sorting.rst @@ -42,7 +42,7 @@ Key Functions ============= -Both :meth:`list.sort` and :func:`sorted` have *key* parameter to specify a +Both :meth:`list.sort` and :func:`sorted` have a *key* parameter to specify a function to be called on each list element prior to making comparisons. For example, here's a case-insensitive string comparison: @@ -89,7 +89,7 @@ The key-function patterns shown above are very common, so Python provides convenience functions to make accessor functions easier and faster. The :mod:`operator` module has :func:`~operator.itemgetter`, -:func:`~operator.attrgetter`, and an :func:`~operator.methodcaller` function. +:func:`~operator.attrgetter`, and a :func:`~operator.methodcaller` function. Using those functions, the above examples become simpler and faster: @@ -114,7 +114,7 @@ ======================== Both :meth:`list.sort` and :func:`sorted` accept a *reverse* parameter with a -boolean value. This is using to flag descending sorts. For example, to get the +boolean value. This is used to flag descending sorts. For example, to get the student data in reverse *age* order: >>> sorted(student_tuples, key=itemgetter(2), reverse=True) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 19:36:07 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Apr 2012 19:36:07 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzkxNTQ6?= =?utf8?q?__Fix_parser_module_to_understand_function_annotations=2E?= Message-ID: http://hg.python.org/cpython/rev/9f57d66689ca changeset: 76635:9f57d66689ca branch: 3.2 parent: 76631:295fec2cd5ed user: Mark Dickinson date: Sun Apr 29 18:34:40 2012 +0100 summary: Issue #9154: Fix parser module to understand function annotations. files: Lib/test/test_parser.py | 21 ++++ Misc/NEWS | 2 + Modules/parsermodule.c | 130 +++++++++++++++------------ 3 files changed, 95 insertions(+), 58 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 @@ -146,6 +146,27 @@ self.check_suite("@funcattrs()\n" "def f(): pass") + # keyword-only arguments + self.check_suite("def f(*, a): pass") + self.check_suite("def f(*, a = 5): pass") + self.check_suite("def f(*, a = 5, b): pass") + self.check_suite("def f(*, a, b = 5): pass") + self.check_suite("def f(*, a, b = 5, **kwds): pass") + self.check_suite("def f(*args, a): pass") + self.check_suite("def f(*args, a = 5): pass") + self.check_suite("def f(*args, a = 5, b): pass") + self.check_suite("def f(*args, a, b = 5): pass") + self.check_suite("def f(*args, a, b = 5, **kwds): pass") + + # function annotations + self.check_suite("def f(a: int): pass") + self.check_suite("def f(a: int = 5): pass") + self.check_suite("def f(*args: list): pass") + self.check_suite("def f(**kwds: dict): pass") + self.check_suite("def f(*, a: int): pass") + self.check_suite("def f(*, a: int = 5): pass") + self.check_suite("def f() -> int: pass") + def test_class_defs(self): self.check_suite("class foo():pass") self.check_suite("class foo(object):pass") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,8 @@ Library ------- +- Issue #9154: Fix parser module to understand function annotations. + - Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a test class that doesn't inherit from TestCase (i.e. a mixin). diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -938,6 +938,7 @@ #define validate_doublestar(ch) validate_terminal(ch, DOUBLESTAR, "**") #define validate_dot(ch) validate_terminal(ch, DOT, ".") #define validate_at(ch) validate_terminal(ch, AT, "@") +#define validate_rarrow(ch) validate_terminal(ch, RARROW, "->") #define validate_name(ch, str) validate_terminal(ch, NAME, str) #define VALIDATER(n) static int validate_##n(node *tree) @@ -1226,68 +1227,68 @@ return 0; } -/* '*' vfpdef (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef +/* '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef * ..or tfpdef in place of vfpdef. vfpdef: NAME; tfpdef: NAME [':' test] */ static int validate_varargslist_trailer(node *tree, int start) { int nch = NCH(tree); - int res = 0, i; - int sym; + int res = 0; if (nch <= start) { err_string("expected variable argument trailer for varargslist"); return 0; } - sym = TYPE(CHILD(tree, start)); - if (sym == STAR) { + if (TYPE(CHILD(tree, start)) == STAR) { /* - * '*' vfpdef (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef + * '*' [vfpdef] */ - if (nch-start == 2) - res = validate_vfpdef(CHILD(tree, start+1)); - else if (nch-start == 5 && TYPE(CHILD(tree, start+2)) == COMMA) - res = (validate_vfpdef(CHILD(tree, start+1)) - && validate_comma(CHILD(tree, start+2)) - && validate_doublestar(CHILD(tree, start+3)) - && validate_vfpdef(CHILD(tree, start+4))); + res = validate_star(CHILD(tree, start++)); + if (res && start < nch && (TYPE(CHILD(tree, start)) == vfpdef || + TYPE(CHILD(tree, start)) == tfpdef)) + res = validate_vfpdef(CHILD(tree, start++)); + /* + * (',' vfpdef ['=' test])* + */ + while (res && start + 1 < nch && ( + TYPE(CHILD(tree, start + 1)) == vfpdef || + TYPE(CHILD(tree, start + 1)) == tfpdef)) { + res = (validate_comma(CHILD(tree, start++)) + && validate_vfpdef(CHILD(tree, start++))); + if (res && start + 1 < nch && TYPE(CHILD(tree, start)) == EQUAL) + res = (validate_equal(CHILD(tree, start++)) + && validate_test(CHILD(tree, start++))); + } + /* + * [',' '**' vfpdef] + */ + if (res && start + 2 < nch && TYPE(CHILD(tree, start+1)) == DOUBLESTAR) + res = (validate_comma(CHILD(tree, start++)) + && validate_doublestar(CHILD(tree, start++)) + && validate_vfpdef(CHILD(tree, start++))); + } + else if (TYPE(CHILD(tree, start)) == DOUBLESTAR) { + /* + * '**' vfpdef + */ + if (start + 1 < nch) + res = (validate_doublestar(CHILD(tree, start++)) + && validate_vfpdef(CHILD(tree, start++))); else { - /* skip over vfpdef (',' vfpdef ['=' test])* */ - i = start + 1; - if (TYPE(CHILD(tree, i)) == vfpdef || - TYPE(CHILD(tree, i)) == tfpdef) { /* skip over vfpdef or tfpdef */ - i += 1; - } - while (res && i+1 < nch) { /* validate (',' vfpdef ['=' test])* */ - res = validate_comma(CHILD(tree, i)); - if (TYPE(CHILD(tree, i+1)) == DOUBLESTAR) - break; - res = res && validate_vfpdef(CHILD(tree, i+1)); - if (res && i+2 < nch && TYPE(CHILD(tree, i+2)) == EQUAL) { - res = res && (i+3 < nch) - && validate_test(CHILD(tree, i+3)); - i += 4; - } - else { - i += 2; - } - } - /* [',' '**' vfpdef] */ - if (res && i+1 < nch && TYPE(CHILD(tree, i+1)) == DOUBLESTAR) { - res = validate_vfpdef(CHILD(tree, i+2)); - } + res = 0; + err_string("expected vfpdef after ** in varargslist trailer"); } } - else if (sym == DOUBLESTAR) { - /* - * '**' NAME - */ - if (nch-start == 2) - res = validate_vfpdef(CHILD(tree, start+1)); + else { + res = 0; + err_string("expected * or ** in varargslist trailer"); } - if (!res) - err_string("illegal variable argument trailer for varargslist"); + + if (res && start != nch) { + res = 0; + err_string("unexpected extra children in varargslist trailer"); + } return res; } @@ -2495,23 +2496,36 @@ return ok; } -/* funcdef: - * - * -5 -4 -3 -2 -1 - * 'def' NAME parameters ':' suite - */ +/* funcdef: 'def' NAME parameters ['->' test] ':' suite */ + static int validate_funcdef(node *tree) { int nch = NCH(tree); - int ok = (validate_ntype(tree, funcdef) - && (nch == 5) - && validate_name(RCHILD(tree, -5), "def") - && validate_ntype(RCHILD(tree, -4), NAME) - && validate_colon(RCHILD(tree, -2)) - && validate_parameters(RCHILD(tree, -3)) - && validate_suite(RCHILD(tree, -1))); - return ok; + int res = validate_ntype(tree, funcdef); + if (res) { + if (nch == 5) { + res = (validate_name(CHILD(tree, 0), "def") + && validate_ntype(CHILD(tree, 1), NAME) + && validate_parameters(CHILD(tree, 2)) + && validate_colon(CHILD(tree, 3)) + && validate_suite(CHILD(tree, 4))); + } + else if (nch == 7) { + res = (validate_name(CHILD(tree, 0), "def") + && validate_ntype(CHILD(tree, 1), NAME) + && validate_parameters(CHILD(tree, 2)) + && validate_rarrow(CHILD(tree, 3)) + && validate_test(CHILD(tree, 4)) + && validate_colon(CHILD(tree, 5)) + && validate_suite(CHILD(tree, 6))); + } + else { + res = 0; + err_string("illegal number of children for funcdef"); + } + } + return res; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 19:36:08 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Apr 2012 19:36:08 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=239154=3A_Merge_fix_from_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/cee5cb877631 changeset: 76636:cee5cb877631 parent: 76634:534cbebd7a71 parent: 76635:9f57d66689ca user: Mark Dickinson date: Sun Apr 29 18:35:56 2012 +0100 summary: Issue #9154: Merge fix from 3.2. files: Lib/test/test_parser.py | 21 ++++ Misc/NEWS | 2 + Modules/parsermodule.c | 130 +++++++++++++++------------ 3 files changed, 95 insertions(+), 58 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 @@ -150,6 +150,27 @@ self.check_suite("@funcattrs()\n" "def f(): pass") + # keyword-only arguments + self.check_suite("def f(*, a): pass") + self.check_suite("def f(*, a = 5): pass") + self.check_suite("def f(*, a = 5, b): pass") + self.check_suite("def f(*, a, b = 5): pass") + self.check_suite("def f(*, a, b = 5, **kwds): pass") + self.check_suite("def f(*args, a): pass") + self.check_suite("def f(*args, a = 5): pass") + self.check_suite("def f(*args, a = 5, b): pass") + self.check_suite("def f(*args, a, b = 5): pass") + self.check_suite("def f(*args, a, b = 5, **kwds): pass") + + # function annotations + self.check_suite("def f(a: int): pass") + self.check_suite("def f(a: int = 5): pass") + self.check_suite("def f(*args: list): pass") + self.check_suite("def f(**kwds: dict): pass") + self.check_suite("def f(*, a: int): pass") + self.check_suite("def f(*, a: int = 5): pass") + self.check_suite("def f() -> int: pass") + def test_class_defs(self): self.check_suite("class foo():pass") self.check_suite("class foo(object):pass") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,6 +84,8 @@ Library ------- +- Issue #9154: Fix parser module to understand function annotations. + - Issue #6085: In http.server.py SimpleHTTPServer.address_string returns the client ip address instead client hostname. Patch by Charles-Fran?ois Natali. diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -940,6 +940,7 @@ #define validate_doublestar(ch) validate_terminal(ch, DOUBLESTAR, "**") #define validate_dot(ch) validate_terminal(ch, DOT, ".") #define validate_at(ch) validate_terminal(ch, AT, "@") +#define validate_rarrow(ch) validate_terminal(ch, RARROW, "->") #define validate_name(ch, str) validate_terminal(ch, NAME, str) #define VALIDATER(n) static int validate_##n(node *tree) @@ -1229,68 +1230,68 @@ return 0; } -/* '*' vfpdef (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef +/* '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef * ..or tfpdef in place of vfpdef. vfpdef: NAME; tfpdef: NAME [':' test] */ static int validate_varargslist_trailer(node *tree, int start) { int nch = NCH(tree); - int res = 0, i; - int sym; + int res = 0; if (nch <= start) { err_string("expected variable argument trailer for varargslist"); return 0; } - sym = TYPE(CHILD(tree, start)); - if (sym == STAR) { + if (TYPE(CHILD(tree, start)) == STAR) { /* - * '*' vfpdef (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef + * '*' [vfpdef] */ - if (nch-start == 2) - res = validate_vfpdef(CHILD(tree, start+1)); - else if (nch-start == 5 && TYPE(CHILD(tree, start+2)) == COMMA) - res = (validate_vfpdef(CHILD(tree, start+1)) - && validate_comma(CHILD(tree, start+2)) - && validate_doublestar(CHILD(tree, start+3)) - && validate_vfpdef(CHILD(tree, start+4))); + res = validate_star(CHILD(tree, start++)); + if (res && start < nch && (TYPE(CHILD(tree, start)) == vfpdef || + TYPE(CHILD(tree, start)) == tfpdef)) + res = validate_vfpdef(CHILD(tree, start++)); + /* + * (',' vfpdef ['=' test])* + */ + while (res && start + 1 < nch && ( + TYPE(CHILD(tree, start + 1)) == vfpdef || + TYPE(CHILD(tree, start + 1)) == tfpdef)) { + res = (validate_comma(CHILD(tree, start++)) + && validate_vfpdef(CHILD(tree, start++))); + if (res && start + 1 < nch && TYPE(CHILD(tree, start)) == EQUAL) + res = (validate_equal(CHILD(tree, start++)) + && validate_test(CHILD(tree, start++))); + } + /* + * [',' '**' vfpdef] + */ + if (res && start + 2 < nch && TYPE(CHILD(tree, start+1)) == DOUBLESTAR) + res = (validate_comma(CHILD(tree, start++)) + && validate_doublestar(CHILD(tree, start++)) + && validate_vfpdef(CHILD(tree, start++))); + } + else if (TYPE(CHILD(tree, start)) == DOUBLESTAR) { + /* + * '**' vfpdef + */ + if (start + 1 < nch) + res = (validate_doublestar(CHILD(tree, start++)) + && validate_vfpdef(CHILD(tree, start++))); else { - /* skip over vfpdef (',' vfpdef ['=' test])* */ - i = start + 1; - if (TYPE(CHILD(tree, i)) == vfpdef || - TYPE(CHILD(tree, i)) == tfpdef) { /* skip over vfpdef or tfpdef */ - i += 1; - } - while (res && i+1 < nch) { /* validate (',' vfpdef ['=' test])* */ - res = validate_comma(CHILD(tree, i)); - if (TYPE(CHILD(tree, i+1)) == DOUBLESTAR) - break; - res = res && validate_vfpdef(CHILD(tree, i+1)); - if (res && i+2 < nch && TYPE(CHILD(tree, i+2)) == EQUAL) { - res = res && (i+3 < nch) - && validate_test(CHILD(tree, i+3)); - i += 4; - } - else { - i += 2; - } - } - /* [',' '**' vfpdef] */ - if (res && i+1 < nch && TYPE(CHILD(tree, i+1)) == DOUBLESTAR) { - res = validate_vfpdef(CHILD(tree, i+2)); - } + res = 0; + err_string("expected vfpdef after ** in varargslist trailer"); } } - else if (sym == DOUBLESTAR) { - /* - * '**' NAME - */ - if (nch-start == 2) - res = validate_vfpdef(CHILD(tree, start+1)); + else { + res = 0; + err_string("expected * or ** in varargslist trailer"); } - if (!res) - err_string("illegal variable argument trailer for varargslist"); + + if (res && start != nch) { + res = 0; + err_string("unexpected extra children in varargslist trailer"); + } return res; } @@ -2525,23 +2526,36 @@ return ok; } -/* funcdef: - * - * -5 -4 -3 -2 -1 - * 'def' NAME parameters ':' suite - */ +/* funcdef: 'def' NAME parameters ['->' test] ':' suite */ + static int validate_funcdef(node *tree) { int nch = NCH(tree); - int ok = (validate_ntype(tree, funcdef) - && (nch == 5) - && validate_name(RCHILD(tree, -5), "def") - && validate_ntype(RCHILD(tree, -4), NAME) - && validate_colon(RCHILD(tree, -2)) - && validate_parameters(RCHILD(tree, -3)) - && validate_suite(RCHILD(tree, -1))); - return ok; + int res = validate_ntype(tree, funcdef); + if (res) { + if (nch == 5) { + res = (validate_name(CHILD(tree, 0), "def") + && validate_ntype(CHILD(tree, 1), NAME) + && validate_parameters(CHILD(tree, 2)) + && validate_colon(CHILD(tree, 3)) + && validate_suite(CHILD(tree, 4))); + } + else if (nch == 7) { + res = (validate_name(CHILD(tree, 0), "def") + && validate_ntype(CHILD(tree, 1), NAME) + && validate_parameters(CHILD(tree, 2)) + && validate_rarrow(CHILD(tree, 3)) + && validate_test(CHILD(tree, 4)) + && validate_colon(CHILD(tree, 5)) + && validate_suite(CHILD(tree, 6))); + } + else { + res = 0; + err_string("illegal number of children for funcdef"); + } + } + return res; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 19:48:12 2012 From: python-checkins at python.org (victor.stinner) Date: Sun, 29 Apr 2012 19:48:12 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314428=3A_Rewrite_t?= =?utf8?q?est=5Fprocess=5Ftime=5Fthreads=28=29_test?= Message-ID: http://hg.python.org/cpython/rev/1255cac63dfc changeset: 76637:1255cac63dfc user: Victor Stinner date: Sun Apr 29 19:46:19 2012 +0200 summary: Issue #14428: Rewrite test_process_time_threads() test time.process_time() is CPU time, not a number of seconds. files: Lib/test/test_time.py | 47 ++++++++++++++++++++++++++---- 1 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -392,20 +392,53 @@ @unittest.skipUnless(threading, 'need threading') def test_process_time_threads(self): - class BusyThread(threading.Thread): + def factorial(n): + if n >= 2: + return n * factorial(n-1) + else: + return 1 + + def use_cpu(n, loops): + for loop in range(loops): + factorial(n) + + class FactorialThread(threading.Thread): + def __init__(self, n, loops): + threading.Thread.__init__(self) + self.n = n + self.loops = loops + def run(self): - while not self.stop: - pass + use_cpu(self.n, self.loops) - thread = BusyThread() - thread.stop = False + # Calibrate use_cpu() to use at least 1 ms of system time + n = 50 + loops = 1 + resolution = time.get_clock_info('process_time').resolution + min_rdt = max(resolution, 0.001) + while 1: + rt1 = time.time() + t1 = time.process_time() + use_cpu(n, loops) + t2 = time.process_time() + rt2 = time.time() + rdt = rt2 - rt1 + if rdt >= min_rdt: + break + loops *= 2 + busy = t2 - t1 + + # Ensure that time.process_time() includes the CPU time of all threads + thread = FactorialThread(n, loops) t1 = time.process_time() thread.start() - time.sleep(0.2) + # Use sleep() instead of thread.join() because thread.join() time may + # be included in time.process_time() depending on its implementation + time.sleep(rdt * 2) t2 = time.process_time() thread.stop = True thread.join() - self.assertGreater(t2 - t1, 0.1) + self.assertGreaterEqual(t2 - t1, busy) @unittest.skipUnless(hasattr(time, 'monotonic'), 'need time.monotonic') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 20:17:18 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Apr 2012 20:17:18 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Remove_untests_for_non-exis?= =?utf8?q?tent_functionality=2E?= Message-ID: http://hg.python.org/cpython/rev/4c0874ed4cfd changeset: 76638:4c0874ed4cfd user: Mark Dickinson date: Sun Apr 29 19:17:05 2012 +0100 summary: Remove untests for non-existent functionality. files: Lib/test/test_float.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -860,16 +860,6 @@ self.assertEqual(str(1e300 * 1e300 * 0), "nan") self.assertEqual(str(-1e300 * 1e300 * 0), "nan") - def notest_float_nan(self): - self.assertTrue(NAN.is_nan()) - self.assertFalse(INF.is_nan()) - self.assertFalse((0.).is_nan()) - - def notest_float_inf(self): - self.assertTrue(INF.is_inf()) - self.assertFalse(NAN.is_inf()) - self.assertFalse((0.).is_inf()) - def test_inf_signs(self): self.assertEqual(copysign(1.0, float('inf')), 1.0) self.assertEqual(copysign(1.0, float('-inf')), -1.0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 20:35:16 2012 From: python-checkins at python.org (sandro.tosi) Date: Sun, 29 Apr 2012 20:35:16 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314691=3A_indent_th?= =?utf8?q?e_traceback_so_the_example_is_highlighted?= Message-ID: http://hg.python.org/cpython/rev/925fbcfbbc45 changeset: 76639:925fbcfbbc45 user: Sandro Tosi date: Sun Apr 29 20:33:28 2012 +0200 summary: Issue #14691: indent the traceback so the example is highlighted files: Doc/library/stdtypes.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2459,7 +2459,7 @@ bytearray(b'z123fg') >>> v[2:3] = b'spam' Traceback (most recent call last): - File "", line 1, in + File "", line 1, in ValueError: memoryview assignment: lvalue and rvalue have different structures >>> v[2:6] = b'spam' >>> data -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 20:40:50 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 29 Apr 2012 20:40:50 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issues_=2313959=2C_14647=3A?= =?utf8?q?_Re-implement_imp=2Ereload=28=29_in_Lib/imp=2Epy=2E?= Message-ID: http://hg.python.org/cpython/rev/eb68502731dd changeset: 76640:eb68502731dd parent: 76637:1255cac63dfc user: Brett Cannon date: Sun Apr 29 14:38:11 2012 -0400 summary: Issues #13959, 14647: Re-implement imp.reload() in Lib/imp.py. Thanks to Eric Snow for the patch. files: Include/pystate.h | 1 - Lib/imp.py | 33 ++++++++- Objects/moduleobject.c | 2 +- Python/import.c | 113 +++------------------------- Python/pystate.c | 2 - Python/pythonrun.c | 4 - 6 files changed, 47 insertions(+), 108 deletions(-) diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -26,7 +26,6 @@ PyObject *sysdict; PyObject *builtins; PyObject *importlib; - PyObject *modules_reloading; PyObject *codec_search_path; PyObject *codec_search_cache; diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -6,7 +6,7 @@ """ # (Probably) need to stay in _imp -from _imp import (lock_held, acquire_lock, release_lock, reload, +from _imp import (lock_held, acquire_lock, release_lock, load_dynamic, get_frozen_object, is_frozen_package, init_builtin, init_frozen, is_builtin, is_frozen, _fix_co_filename) @@ -207,3 +207,34 @@ encoding = tokenize.detect_encoding(file.readline)[0] file = open(file_path, mode, encoding=encoding) return file, file_path, (suffix, mode, type_) + + +_RELOADING = {} + +def reload(module): + """Reload the module and return it. + + The module must have been successfully imported before. + + """ + if not module or type(module) != type(sys): + raise TypeError("reload() argument must be module") + name = module.__name__ + if name not in sys.modules: + msg = "module {} not in sys.modules" + raise ImportError(msg.format(name), name=name) + if name in _RELOADING: + return _RELOADING[name] + _RELOADING[name] = module + try: + parent_name = name.rpartition('.')[0] + if parent_name and parent_name not in sys.modules: + msg = "parent {!r} not in sys.modules" + raise ImportError(msg.format(parentname), name=parent_name) + return module.__loader__.load_module(name) + finally: + try: + del _RELOADING[name] + except KeyError: + pass + diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -285,7 +285,7 @@ pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - if (PyUnicode_READ_CHAR(key, 0) == '_' && + if (PyUnicode_READ_CHAR(key, 0) == '_' && PyUnicode_READ_CHAR(key, 1) != '_') { if (Py_VerboseFlag > 1) { const char *s = _PyUnicode_AsString(key); diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -410,14 +410,6 @@ #endif } -static void -imp_modules_reloading_clear(void) -{ - PyInterpreterState *interp = PyThreadState_Get()->interp; - if (interp->modules_reloading != NULL) - PyDict_Clear(interp->modules_reloading); -} - /* Helper for sys */ PyObject * @@ -575,7 +567,6 @@ PyDict_Clear(modules); interp->modules = NULL; Py_DECREF(modules); - Py_CLEAR(interp->modules_reloading); } @@ -1783,87 +1774,23 @@ PyObject * PyImport_ReloadModule(PyObject *m) { - PyInterpreterState *interp = PyThreadState_Get()->interp; - PyObject *modules_reloading = interp->modules_reloading; + _Py_IDENTIFIER(reload); + PyObject *reloaded_module = NULL; PyObject *modules = PyImport_GetModuleDict(); - PyObject *loader = NULL, *existing_m = NULL; - PyObject *name; - Py_ssize_t subname_start; - PyObject *newm = NULL; - _Py_IDENTIFIER(__loader__); - _Py_IDENTIFIER(load_module); - - if (modules_reloading == NULL) { - Py_FatalError("PyImport_ReloadModule: " - "no modules_reloading dictionary!"); - return NULL; + PyObject *imp = PyDict_GetItemString(modules, "imp"); + if (imp == NULL) { + imp = PyImport_ImportModule("imp"); + if (imp == NULL) { + return NULL; + } + } + else { + Py_INCREF(imp); } - if (m == NULL || !PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, - "reload() argument must be module"); - return NULL; - } - name = PyModule_GetNameObject(m); - if (name == NULL || PyUnicode_READY(name) == -1) - return NULL; - if (m != PyDict_GetItem(modules, name)) { - PyErr_Format(PyExc_ImportError, - "reload(): module %R not in sys.modules", - name); - Py_DECREF(name); - return NULL; - } - existing_m = PyDict_GetItem(modules_reloading, name); - if (existing_m != NULL) { - /* Due to a recursive reload, this module is already - being reloaded. */ - Py_DECREF(name); - Py_INCREF(existing_m); - return existing_m; - } - if (PyDict_SetItem(modules_reloading, name, m) < 0) { - Py_DECREF(name); - return NULL; - } - - subname_start = PyUnicode_FindChar(name, '.', 0, - PyUnicode_GET_LENGTH(name), -1); - if (subname_start != -1) { - PyObject *parentname, *parent; - parentname = PyUnicode_Substring(name, 0, subname_start); - if (parentname == NULL) { - goto error; - } - parent = PyDict_GetItem(modules, parentname); - Py_XDECREF(parent); - if (parent == NULL) { - PyErr_Format(PyExc_ImportError, - "reload(): parent %R not in sys.modules", - parentname); - goto error; - } - } - - loader = _PyObject_GetAttrId(m, &PyId___loader__); - if (loader == NULL) { - goto error; - } - newm = _PyObject_CallMethodId(loader, &PyId_load_module, "O", name); - Py_DECREF(loader); - if (newm == NULL) { - /* load_module probably removed name from modules because of - * the error. Put back the original module object. We're - * going to return NULL in this case regardless of whether - * replacing name succeeds, so the return value is ignored. - */ - PyDict_SetItem(modules, name, m); - } - -error: - imp_modules_reloading_clear(); - Py_DECREF(name); - return newm; + reloaded_module = _PyObject_CallMethodId(imp, &PyId_reload, "O", m); + Py_DECREF(imp); + return reloaded_module; } @@ -2160,17 +2087,6 @@ #endif /* HAVE_DYNAMIC_LOADING */ -static PyObject * -imp_reload(PyObject *self, PyObject *v) -{ - return PyImport_ReloadModule(v); -} - -PyDoc_STRVAR(doc_reload, -"reload(module) -> module\n\ -\n\ -Reload the module. The module must have been successfully imported before."); - /* Doc strings */ @@ -2214,7 +2130,6 @@ {"lock_held", imp_lock_held, METH_NOARGS, doc_lock_held}, {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, - {"reload", imp_reload, METH_O, doc_reload}, {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, {"is_frozen_package", imp_is_frozen_package, METH_VARARGS}, {"init_builtin", imp_init_builtin, METH_VARARGS}, diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -69,7 +69,6 @@ Py_FatalError("Can't initialize threads for interpreter"); #endif interp->modules = NULL; - interp->modules_reloading = NULL; interp->modules_by_index = NULL; interp->sysdict = NULL; interp->builtins = NULL; @@ -114,7 +113,6 @@ Py_CLEAR(interp->codec_error_registry); Py_CLEAR(interp->modules); Py_CLEAR(interp->modules_by_index); - Py_CLEAR(interp->modules_reloading); Py_CLEAR(interp->sysdict); Py_CLEAR(interp->builtins); Py_CLEAR(interp->importlib); diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -314,9 +314,6 @@ interp->modules = PyDict_New(); if (interp->modules == NULL) Py_FatalError("Py_Initialize: can't make modules dictionary"); - interp->modules_reloading = PyDict_New(); - if (interp->modules_reloading == NULL) - Py_FatalError("Py_Initialize: can't make modules_reloading dictionary"); /* Init Unicode implementation; relies on the codec registry */ if (_PyUnicode_Init() < 0) @@ -680,7 +677,6 @@ /* XXX The following is lax in error checking */ interp->modules = PyDict_New(); - interp->modules_reloading = PyDict_New(); bimod = _PyImport_FindBuiltin("builtins"); if (bimod != NULL) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 20:40:51 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 29 Apr 2012 20:40:51 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/40a05f9eb4c6 changeset: 76641:40a05f9eb4c6 parent: 76640:eb68502731dd parent: 76639:925fbcfbbc45 user: Brett Cannon date: Sun Apr 29 14:38:57 2012 -0400 summary: merge files: Doc/library/stdtypes.rst | 2 +- Lib/test/test_float.py | 10 ---------- 2 files changed, 1 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 @@ -2459,7 +2459,7 @@ bytearray(b'z123fg') >>> v[2:3] = b'spam' Traceback (most recent call last): - File "", line 1, in + File "", line 1, in ValueError: memoryview assignment: lvalue and rvalue have different structures >>> v[2:6] = b'spam' >>> data diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -860,16 +860,6 @@ self.assertEqual(str(1e300 * 1e300 * 0), "nan") self.assertEqual(str(-1e300 * 1e300 * 0), "nan") - def notest_float_nan(self): - self.assertTrue(NAN.is_nan()) - self.assertFalse(INF.is_nan()) - self.assertFalse((0.).is_nan()) - - def notest_float_inf(self): - self.assertTrue(INF.is_inf()) - self.assertFalse(NAN.is_inf()) - self.assertFalse((0.).is_inf()) - def test_inf_signs(self): self.assertEqual(copysign(1.0, float('inf')), 1.0) self.assertEqual(copysign(1.0, float('-inf')), -1.0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 20:40:52 2012 From: python-checkins at python.org (brett.cannon) Date: Sun, 29 Apr 2012 20:40:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Re-indent=2E?= Message-ID: http://hg.python.org/cpython/rev/02f0bd296169 changeset: 76642:02f0bd296169 user: Brett Cannon date: Sun Apr 29 14:40:43 2012 -0400 summary: Re-indent. files: Lib/imp.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -237,4 +237,3 @@ del _RELOADING[name] except KeyError: pass - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 21:28:35 2012 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 29 Apr 2012 21:28:35 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Flatten_the_lru_cache_keywo?= =?utf8?q?rd_args_tuple_for_better_memory_utilization=2E?= Message-ID: http://hg.python.org/cpython/rev/399cb1afb747 changeset: 76643:399cb1afb747 user: Raymond Hettinger date: Sun Apr 29 12:28:02 2012 -0700 summary: Flatten the lru cache keyword args tuple for better memory utilization. files: Lib/functools.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -185,7 +185,9 @@ key = args if kwds: sorted_items = tuple(sorted(kwds.items())) - key += kwd_mark + sorted_items + key += kwd_mark + key += tuple(k for k, v in sorted_items) + key += tuple(v for k, v in sorted_items) if typed: key += tuple(type(v) for v in args) if kwds: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 22:42:08 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 29 Apr 2012 22:42:08 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEwOTQx?= =?utf8?q?=3A_Fix_imaplib=2EInternaldate2tuple_to_produce_correct_result_n?= =?utf8?q?ear?= Message-ID: http://hg.python.org/cpython/rev/90b9781ccb5f changeset: 76644:90b9781ccb5f branch: 3.2 parent: 76635:9f57d66689ca user: Alexander Belopolsky date: Sun Apr 29 15:56:49 2012 -0400 summary: Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near the DST transition. Patch by Joe Peterson. files: Lib/imaplib.py | 16 ++----------- Lib/test/support.py | 31 +++++++++++++++++++++++++++- Lib/test/test_imaplib.py | 9 +++++++- Misc/ACKS | 1 + Misc/NEWS | 3 ++ 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -22,7 +22,7 @@ __version__ = "2.58" -import binascii, errno, random, re, socket, subprocess, sys, time +import binascii, errno, random, re, socket, subprocess, sys, time, calendar try: import ssl @@ -1340,19 +1340,9 @@ zone = -zone tt = (year, mon, day, hour, min, sec, -1, -1, -1) + utc = calendar.timegm(tt) - zone - utc = time.mktime(tt) - - # Following is necessary because the time module has no 'mkgmtime'. - # 'mktime' assumes arg in local timezone, so adds timezone/altzone. - - lt = time.localtime(utc) - if time.daylight and lt[-1]: - zone = zone + time.altzone - else: - zone = zone + time.timezone - - return time.localtime(utc - zone) + return time.localtime(utc) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -53,7 +53,7 @@ "reap_children", "cpython_only", "check_impl_detail", "get_attribute", "swap_item", "swap_attr", "requires_IEEE_754", "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", - "import_fresh_module", "failfast", + "import_fresh_module", "failfast", "run_with_tz" ] class Error(Exception): @@ -1021,6 +1021,35 @@ return decorator #======================================================================= +# Decorator for running a function in a specific timezone, correctly +# resetting it afterwards. + +def run_with_tz(tz): + def decorator(func): + def inner(*args, **kwds): + if 'TZ' in os.environ: + orig_tz = os.environ['TZ'] + else: + orig_tz = None + os.environ['TZ'] = tz + time.tzset() + + # now run the function, resetting the tz on exceptions + try: + return func(*args, **kwds) + finally: + if orig_tz == None: + del os.environ['TZ'] + else: + os.environ['TZ'] = orig_tz + time.tzset() + + inner.__name__ = func.__name__ + inner.__doc__ = func.__doc__ + return inner + return decorator + +#======================================================================= # Big-memory-test support. Separate from 'resources' because memory use # should be configurable. diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -11,7 +11,7 @@ import time import calendar -from test.support import reap_threads, verbose, transient_internet +from test.support import reap_threads, verbose, transient_internet, run_with_tz import unittest try: @@ -36,6 +36,13 @@ b'25 (INTERNALDATE "31-Dec-1999 12:30:00 -1130")') self.assertEqual(time.mktime(tt), t0) + @run_with_tz('MST+07MDT,M4.1.0,M10.5.0') + def test_Internaldate2tuple_issue10941(self): + self.assertNotEqual(imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 02:30:00 +0000")'), + imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 03:30:00 +0000")')) + def test_that_Time2Internaldate_returns_a_result(self): # We can check only that it successfully produces a result, # not the correctness of the result itself, since the result diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -702,6 +702,7 @@ Alexandre Parenteau Dan Parisien Harri Pasanen +Joe Peterson Randy Pausch Samuele Pedroni Marcel van der Peijl diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,9 @@ Library ------- +- Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near + the DST transition. Patch by Joe Peterson. + - Issue #9154: Fix parser module to understand function annotations. - Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 22:42:09 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 29 Apr 2012 22:42:09 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2310941=3A_Fix_imaplib=2EInternaldate2tuple_to_produc?= =?utf8?q?e_correct_result_near?= Message-ID: http://hg.python.org/cpython/rev/6e029b6c142a changeset: 76645:6e029b6c142a parent: 76642:02f0bd296169 parent: 76644:90b9781ccb5f user: Alexander Belopolsky date: Sun Apr 29 16:12:27 2012 -0400 summary: Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near the DST transition. Patch by Joe Peterson. files: Lib/imaplib.py | 16 ++----------- Lib/test/support.py | 31 +++++++++++++++++++++++++++- Lib/test/test_imaplib.py | 9 +++++++- Misc/ACKS | 1 + Misc/NEWS | 3 ++ 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -22,7 +22,7 @@ __version__ = "2.58" -import binascii, errno, random, re, socket, subprocess, sys, time +import binascii, errno, random, re, socket, subprocess, sys, time, calendar try: import ssl @@ -1347,19 +1347,9 @@ zone = -zone tt = (year, mon, day, hour, min, sec, -1, -1, -1) + utc = calendar.timegm(tt) - zone - utc = time.mktime(tt) - - # Following is necessary because the time module has no 'mkgmtime'. - # 'mktime' assumes arg in local timezone, so adds timezone/altzone. - - lt = time.localtime(utc) - if time.daylight and lt[-1]: - zone = zone + time.altzone - else: - zone = zone + time.timezone - - return time.localtime(utc - zone) + return time.localtime(utc) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -57,7 +57,7 @@ "get_attribute", "swap_item", "swap_attr", "requires_IEEE_754", "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", "import_fresh_module", "requires_zlib", "PIPE_MAX_SIZE", "failfast", - "anticipate_failure" + "anticipate_failure", "run_with_tz" ] class Error(Exception): @@ -1100,6 +1100,35 @@ return decorator #======================================================================= +# Decorator for running a function in a specific timezone, correctly +# resetting it afterwards. + +def run_with_tz(tz): + def decorator(func): + def inner(*args, **kwds): + if 'TZ' in os.environ: + orig_tz = os.environ['TZ'] + else: + orig_tz = None + os.environ['TZ'] = tz + time.tzset() + + # now run the function, resetting the tz on exceptions + try: + return func(*args, **kwds) + finally: + if orig_tz == None: + del os.environ['TZ'] + else: + os.environ['TZ'] = orig_tz + time.tzset() + + inner.__name__ = func.__name__ + inner.__doc__ = func.__doc__ + return inner + return decorator + +#======================================================================= # Big-memory-test support. Separate from 'resources' because memory use # should be configurable. diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -11,7 +11,7 @@ import time import calendar -from test.support import reap_threads, verbose, transient_internet +from test.support import reap_threads, verbose, transient_internet, run_with_tz import unittest try: @@ -36,6 +36,13 @@ b'25 (INTERNALDATE "31-Dec-1999 12:30:00 -1130")') self.assertEqual(time.mktime(tt), t0) + @run_with_tz('MST+07MDT,M4.1.0,M10.5.0') + def test_Internaldate2tuple_issue10941(self): + self.assertNotEqual(imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 02:30:00 +0000")'), + imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 03:30:00 +0000")')) + def test_that_Time2Internaldate_returns_a_result(self): # We can check only that it successfully produces a result, # not the correctness of the result itself, since the result diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -770,6 +770,7 @@ Dan Parisien Harri Pasanen Ga?l Pasgrimaud +Joe Peterson Randy Pausch Samuele Pedroni Marcel van der Peijl diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,6 +84,9 @@ Library ------- +- Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near + the DST transition. Patch by Joe Peterson. + - Issue #9154: Fix parser module to understand function annotations. - Issue #6085: In http.server.py SimpleHTTPServer.address_string returns the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 22:42:10 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 29 Apr 2012 22:42:10 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/e14ed98fc33c changeset: 76646:e14ed98fc33c parent: 76643:399cb1afb747 parent: 76645:6e029b6c142a user: Alexander Belopolsky date: Sun Apr 29 16:34:43 2012 -0400 summary: merge files: Lib/imaplib.py | 16 ++----------- Lib/test/support.py | 31 +++++++++++++++++++++++++++- Lib/test/test_imaplib.py | 9 +++++++- Misc/ACKS | 1 + Misc/NEWS | 3 ++ 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -22,7 +22,7 @@ __version__ = "2.58" -import binascii, errno, random, re, socket, subprocess, sys, time +import binascii, errno, random, re, socket, subprocess, sys, time, calendar try: import ssl @@ -1347,19 +1347,9 @@ zone = -zone tt = (year, mon, day, hour, min, sec, -1, -1, -1) + utc = calendar.timegm(tt) - zone - utc = time.mktime(tt) - - # Following is necessary because the time module has no 'mkgmtime'. - # 'mktime' assumes arg in local timezone, so adds timezone/altzone. - - lt = time.localtime(utc) - if time.daylight and lt[-1]: - zone = zone + time.altzone - else: - zone = zone + time.timezone - - return time.localtime(utc - zone) + return time.localtime(utc) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -57,7 +57,7 @@ "get_attribute", "swap_item", "swap_attr", "requires_IEEE_754", "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", "import_fresh_module", "requires_zlib", "PIPE_MAX_SIZE", "failfast", - "anticipate_failure" + "anticipate_failure", "run_with_tz" ] class Error(Exception): @@ -1100,6 +1100,35 @@ return decorator #======================================================================= +# Decorator for running a function in a specific timezone, correctly +# resetting it afterwards. + +def run_with_tz(tz): + def decorator(func): + def inner(*args, **kwds): + if 'TZ' in os.environ: + orig_tz = os.environ['TZ'] + else: + orig_tz = None + os.environ['TZ'] = tz + time.tzset() + + # now run the function, resetting the tz on exceptions + try: + return func(*args, **kwds) + finally: + if orig_tz == None: + del os.environ['TZ'] + else: + os.environ['TZ'] = orig_tz + time.tzset() + + inner.__name__ = func.__name__ + inner.__doc__ = func.__doc__ + return inner + return decorator + +#======================================================================= # Big-memory-test support. Separate from 'resources' because memory use # should be configurable. diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -11,7 +11,7 @@ import time import calendar -from test.support import reap_threads, verbose, transient_internet +from test.support import reap_threads, verbose, transient_internet, run_with_tz import unittest try: @@ -36,6 +36,13 @@ b'25 (INTERNALDATE "31-Dec-1999 12:30:00 -1130")') self.assertEqual(time.mktime(tt), t0) + @run_with_tz('MST+07MDT,M4.1.0,M10.5.0') + def test_Internaldate2tuple_issue10941(self): + self.assertNotEqual(imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 02:30:00 +0000")'), + imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 03:30:00 +0000")')) + def test_that_Time2Internaldate_returns_a_result(self): # We can check only that it successfully produces a result, # not the correctness of the result itself, since the result diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -770,6 +770,7 @@ Dan Parisien Harri Pasanen Ga?l Pasgrimaud +Joe Peterson Randy Pausch Samuele Pedroni Marcel van der Peijl diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,6 +84,9 @@ Library ------- +- Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near + the DST transition. Patch by Joe Peterson. + - Issue #9154: Fix parser module to understand function annotations. - Issue #6085: In http.server.py SimpleHTTPServer.address_string returns the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 23:20:06 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Apr 2012 23:20:06 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0Njk2?= =?utf8?q?=3A_Fix_parser_module_to_understand_=27nonlocal=27_declarations?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/b7e491b9094f changeset: 76647:b7e491b9094f branch: 3.2 parent: 76644:90b9781ccb5f user: Mark Dickinson date: Sun Apr 29 22:18:31 2012 +0100 summary: Issue #14696: Fix parser module to understand 'nonlocal' declarations. files: Lib/test/test_parser.py | 10 +++++++ Misc/NEWS | 2 + Modules/parsermodule.c | 41 +++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 5 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 @@ -57,6 +57,16 @@ " if (yield):\n" " yield x\n") + def test_nonlocal_statement(self): + self.check_suite("def f():\n" + " x = 0\n" + " def g():\n" + " nonlocal x\n") + self.check_suite("def f():\n" + " x = y = 0\n" + " def g():\n" + " nonlocal x, y\n") + def test_expressions(self): self.check_expr("foo(1)") self.check_expr("[1, 2, 3]") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,8 @@ Library ------- +- Issue #14696: Fix parser module to understand 'nonlocal' declarations. + - Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near the DST transition. Patch by Joe Peterson. diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -954,7 +954,8 @@ VALIDATER(return_stmt); VALIDATER(raise_stmt); VALIDATER(import_stmt); VALIDATER(import_stmt); VALIDATER(import_name); VALIDATER(yield_stmt); -VALIDATER(global_stmt); VALIDATER(assert_stmt); +VALIDATER(global_stmt); VALIDATER(nonlocal_stmt); +VALIDATER(assert_stmt); VALIDATER(compound_stmt); VALIDATER(test_or_star_expr); VALIDATER(while); VALIDATER(for); VALIDATER(try); VALIDATER(except_clause); @@ -1477,6 +1478,7 @@ || (ntype == flow_stmt) || (ntype == import_stmt) || (ntype == global_stmt) + || (ntype == nonlocal_stmt) || (ntype == assert_stmt)) res = validate_node(CHILD(tree, 0)); else { @@ -1834,8 +1836,10 @@ } - - +/* global_stmt: + * + * 'global' NAME (',' NAME)* + */ static int validate_global_stmt(node *tree) { @@ -1857,6 +1861,30 @@ return (res); } +/* nonlocal_stmt: + * + * 'nonlocal' NAME (',' NAME)* + */ +static int +validate_nonlocal_stmt(node *tree) +{ + int j; + int nch = NCH(tree); + int res = (validate_ntype(tree, nonlocal_stmt) + && is_even(nch) && (nch >= 2)); + + if (!res && !PyErr_Occurred()) + err_string("illegal nonlocal statement"); + + if (res) + res = (validate_name(CHILD(tree, 0), "nonlocal") + && validate_ntype(CHILD(tree, 1), NAME)); + for (j = 2; res && (j < nch); j += 2) + res = (validate_comma(CHILD(tree, j)) + && validate_ntype(CHILD(tree, j + 1), NAME)); + + return res; +} /* assert_stmt: * @@ -2921,8 +2949,8 @@ break; case small_stmt: /* - * expr_stmt | del_stmt | pass_stmt | flow_stmt - * | import_stmt | global_stmt | assert_stmt + * expr_stmt | del_stmt | pass_stmt | flow_stmt | + * import_stmt | global_stmt | nonlocal_stmt | assert_stmt */ res = validate_small_stmt(tree); break; @@ -2989,6 +3017,9 @@ case global_stmt: res = validate_global_stmt(tree); break; + case nonlocal_stmt: + res = validate_nonlocal_stmt(tree); + break; case assert_stmt: res = validate_assert_stmt(tree); break; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 23:20:07 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Apr 2012 23:20:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2314696=3A_Merge_from_3=2E2?= Message-ID: http://hg.python.org/cpython/rev/5acddc7c666d changeset: 76648:5acddc7c666d parent: 76646:e14ed98fc33c parent: 76647:b7e491b9094f user: Mark Dickinson date: Sun Apr 29 22:20:01 2012 +0100 summary: Issue #14696: Merge from 3.2 files: Lib/test/test_parser.py | 10 +++++++ Misc/NEWS | 2 + Modules/parsermodule.c | 41 +++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 5 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 @@ -61,6 +61,16 @@ " if (yield):\n" " yield x\n") + def test_nonlocal_statement(self): + self.check_suite("def f():\n" + " x = 0\n" + " def g():\n" + " nonlocal x\n") + self.check_suite("def f():\n" + " x = y = 0\n" + " def g():\n" + " nonlocal x, y\n") + def test_expressions(self): self.check_expr("foo(1)") self.check_expr("[1, 2, 3]") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,6 +84,8 @@ Library ------- +- Issue #14696: Fix parser module to understand 'nonlocal' declarations. + - Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near the DST transition. Patch by Joe Peterson. diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -956,7 +956,8 @@ VALIDATER(return_stmt); VALIDATER(raise_stmt); VALIDATER(import_stmt); VALIDATER(import_stmt); VALIDATER(import_name); VALIDATER(yield_stmt); -VALIDATER(global_stmt); VALIDATER(assert_stmt); +VALIDATER(global_stmt); VALIDATER(nonlocal_stmt); +VALIDATER(assert_stmt); VALIDATER(compound_stmt); VALIDATER(test_or_star_expr); VALIDATER(while); VALIDATER(for); VALIDATER(try); VALIDATER(except_clause); @@ -1480,6 +1481,7 @@ || (ntype == flow_stmt) || (ntype == import_stmt) || (ntype == global_stmt) + || (ntype == nonlocal_stmt) || (ntype == assert_stmt)) res = validate_node(CHILD(tree, 0)); else { @@ -1864,8 +1866,10 @@ } - - +/* global_stmt: + * + * 'global' NAME (',' NAME)* + */ static int validate_global_stmt(node *tree) { @@ -1887,6 +1891,30 @@ return (res); } +/* nonlocal_stmt: + * + * 'nonlocal' NAME (',' NAME)* + */ +static int +validate_nonlocal_stmt(node *tree) +{ + int j; + int nch = NCH(tree); + int res = (validate_ntype(tree, nonlocal_stmt) + && is_even(nch) && (nch >= 2)); + + if (!res && !PyErr_Occurred()) + err_string("illegal nonlocal statement"); + + if (res) + res = (validate_name(CHILD(tree, 0), "nonlocal") + && validate_ntype(CHILD(tree, 1), NAME)); + for (j = 2; res && (j < nch); j += 2) + res = (validate_comma(CHILD(tree, j)) + && validate_ntype(CHILD(tree, j + 1), NAME)); + + return res; +} /* assert_stmt: * @@ -2951,8 +2979,8 @@ break; case small_stmt: /* - * expr_stmt | del_stmt | pass_stmt | flow_stmt - * | import_stmt | global_stmt | assert_stmt + * expr_stmt | del_stmt | pass_stmt | flow_stmt | + * import_stmt | global_stmt | nonlocal_stmt | assert_stmt */ res = validate_small_stmt(tree); break; @@ -3019,6 +3047,9 @@ case global_stmt: res = validate_global_stmt(tree); break; + case nonlocal_stmt: + res = validate_nonlocal_stmt(tree); + break; case assert_stmt: res = validate_assert_stmt(tree); break; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 23:57:23 2012 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 29 Apr 2012 23:57:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Factor_out_shared_variables?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/2adcd28a5a3a changeset: 76649:2adcd28a5a3a parent: 76643:399cb1afb747 user: Raymond Hettinger date: Sun Apr 29 14:55:27 2012 -0700 summary: Factor out shared variables. files: Lib/functools.py | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -167,18 +167,20 @@ # The internals of the lru_cache are encapsulated for thread safety and # to allow the implementation to change (including a possible C version). + # Constants shared by all lru cache instances: + kwd_mark = (object(),) # separate positional and keyword args + sentinel = object() # unique object used to signal cache misses + _len = len # localize the global len() function + PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields + def decorating_function(user_function): cache = {} hits = misses = 0 - kwd_mark = (object(),) # separate positional and keyword args cache_get = cache.get # bound method to lookup a key or return None - sentinel = object() # unique object used with cache_get - _len = len # localize the global len() function lock = Lock() # because linkedlist updates aren't threadsafe root = [] # root of the circular doubly linked list root[:] = [root, root, None, None] # initialize by pointing to self - PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields def make_key(args, kwds, typed, tuple=tuple, sorted=sorted, type=type): # build a cache key from positional and keyword args -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Apr 29 23:57:24 2012 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 29 Apr 2012 23:57:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/e393d83d6877 changeset: 76650:e393d83d6877 parent: 76649:2adcd28a5a3a parent: 76648:5acddc7c666d user: Raymond Hettinger date: Sun Apr 29 14:57:05 2012 -0700 summary: merge files: Lib/imaplib.py | 16 ++-------- Lib/test/support.py | 31 ++++++++++++++++++++- Lib/test/test_imaplib.py | 9 +++++- Lib/test/test_parser.py | 10 ++++++ Misc/ACKS | 1 + Misc/NEWS | 5 +++ Modules/parsermodule.c | 41 ++++++++++++++++++++++++--- 7 files changed, 93 insertions(+), 20 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -22,7 +22,7 @@ __version__ = "2.58" -import binascii, errno, random, re, socket, subprocess, sys, time +import binascii, errno, random, re, socket, subprocess, sys, time, calendar try: import ssl @@ -1347,19 +1347,9 @@ zone = -zone tt = (year, mon, day, hour, min, sec, -1, -1, -1) + utc = calendar.timegm(tt) - zone - utc = time.mktime(tt) - - # Following is necessary because the time module has no 'mkgmtime'. - # 'mktime' assumes arg in local timezone, so adds timezone/altzone. - - lt = time.localtime(utc) - if time.daylight and lt[-1]: - zone = zone + time.altzone - else: - zone = zone + time.timezone - - return time.localtime(utc - zone) + return time.localtime(utc) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -57,7 +57,7 @@ "get_attribute", "swap_item", "swap_attr", "requires_IEEE_754", "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", "import_fresh_module", "requires_zlib", "PIPE_MAX_SIZE", "failfast", - "anticipate_failure" + "anticipate_failure", "run_with_tz" ] class Error(Exception): @@ -1100,6 +1100,35 @@ return decorator #======================================================================= +# Decorator for running a function in a specific timezone, correctly +# resetting it afterwards. + +def run_with_tz(tz): + def decorator(func): + def inner(*args, **kwds): + if 'TZ' in os.environ: + orig_tz = os.environ['TZ'] + else: + orig_tz = None + os.environ['TZ'] = tz + time.tzset() + + # now run the function, resetting the tz on exceptions + try: + return func(*args, **kwds) + finally: + if orig_tz == None: + del os.environ['TZ'] + else: + os.environ['TZ'] = orig_tz + time.tzset() + + inner.__name__ = func.__name__ + inner.__doc__ = func.__doc__ + return inner + return decorator + +#======================================================================= # Big-memory-test support. Separate from 'resources' because memory use # should be configurable. diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -11,7 +11,7 @@ import time import calendar -from test.support import reap_threads, verbose, transient_internet +from test.support import reap_threads, verbose, transient_internet, run_with_tz import unittest try: @@ -36,6 +36,13 @@ b'25 (INTERNALDATE "31-Dec-1999 12:30:00 -1130")') self.assertEqual(time.mktime(tt), t0) + @run_with_tz('MST+07MDT,M4.1.0,M10.5.0') + def test_Internaldate2tuple_issue10941(self): + self.assertNotEqual(imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 02:30:00 +0000")'), + imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 03:30:00 +0000")')) + def test_that_Time2Internaldate_returns_a_result(self): # We can check only that it successfully produces a result, # not the correctness of the result itself, since the result 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 @@ -61,6 +61,16 @@ " if (yield):\n" " yield x\n") + def test_nonlocal_statement(self): + self.check_suite("def f():\n" + " x = 0\n" + " def g():\n" + " nonlocal x\n") + self.check_suite("def f():\n" + " x = y = 0\n" + " def g():\n" + " nonlocal x, y\n") + def test_expressions(self): self.check_expr("foo(1)") self.check_expr("[1, 2, 3]") diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -770,6 +770,7 @@ Dan Parisien Harri Pasanen Ga?l Pasgrimaud +Joe Peterson Randy Pausch Samuele Pedroni Marcel van der Peijl diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,6 +84,11 @@ Library ------- +- Issue #14696: Fix parser module to understand 'nonlocal' declarations. + +- Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near + the DST transition. Patch by Joe Peterson. + - Issue #9154: Fix parser module to understand function annotations. - Issue #6085: In http.server.py SimpleHTTPServer.address_string returns the diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -956,7 +956,8 @@ VALIDATER(return_stmt); VALIDATER(raise_stmt); VALIDATER(import_stmt); VALIDATER(import_stmt); VALIDATER(import_name); VALIDATER(yield_stmt); -VALIDATER(global_stmt); VALIDATER(assert_stmt); +VALIDATER(global_stmt); VALIDATER(nonlocal_stmt); +VALIDATER(assert_stmt); VALIDATER(compound_stmt); VALIDATER(test_or_star_expr); VALIDATER(while); VALIDATER(for); VALIDATER(try); VALIDATER(except_clause); @@ -1480,6 +1481,7 @@ || (ntype == flow_stmt) || (ntype == import_stmt) || (ntype == global_stmt) + || (ntype == nonlocal_stmt) || (ntype == assert_stmt)) res = validate_node(CHILD(tree, 0)); else { @@ -1864,8 +1866,10 @@ } - - +/* global_stmt: + * + * 'global' NAME (',' NAME)* + */ static int validate_global_stmt(node *tree) { @@ -1887,6 +1891,30 @@ return (res); } +/* nonlocal_stmt: + * + * 'nonlocal' NAME (',' NAME)* + */ +static int +validate_nonlocal_stmt(node *tree) +{ + int j; + int nch = NCH(tree); + int res = (validate_ntype(tree, nonlocal_stmt) + && is_even(nch) && (nch >= 2)); + + if (!res && !PyErr_Occurred()) + err_string("illegal nonlocal statement"); + + if (res) + res = (validate_name(CHILD(tree, 0), "nonlocal") + && validate_ntype(CHILD(tree, 1), NAME)); + for (j = 2; res && (j < nch); j += 2) + res = (validate_comma(CHILD(tree, j)) + && validate_ntype(CHILD(tree, j + 1), NAME)); + + return res; +} /* assert_stmt: * @@ -2951,8 +2979,8 @@ break; case small_stmt: /* - * expr_stmt | del_stmt | pass_stmt | flow_stmt - * | import_stmt | global_stmt | assert_stmt + * expr_stmt | del_stmt | pass_stmt | flow_stmt | + * import_stmt | global_stmt | nonlocal_stmt | assert_stmt */ res = validate_small_stmt(tree); break; @@ -3019,6 +3047,9 @@ case global_stmt: res = validate_global_stmt(tree); break; + case nonlocal_stmt: + res = validate_nonlocal_stmt(tree); + break; case assert_stmt: res = validate_assert_stmt(tree); break; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 00:20:20 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 30 Apr 2012 00:20:20 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_fixed_test=5Fim?= =?utf8?q?aplib_failure_on_Win?= Message-ID: http://hg.python.org/cpython/rev/f23222d734bd changeset: 76651:f23222d734bd branch: 3.2 parent: 76647:b7e491b9094f user: Alexander Belopolsky date: Sun Apr 29 18:16:46 2012 -0400 summary: fixed test_imaplib failure on Win files: Lib/test/support.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -1027,12 +1027,16 @@ def run_with_tz(tz): def decorator(func): def inner(*args, **kwds): + try: + tzset = time.tzset + except AttributeError: + raise unittest.SkipTest("tzset required") if 'TZ' in os.environ: orig_tz = os.environ['TZ'] else: orig_tz = None os.environ['TZ'] = tz - time.tzset() + tzset() # now run the function, resetting the tz on exceptions try: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 00:20:21 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 30 Apr 2012 00:20:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_merged?= Message-ID: http://hg.python.org/cpython/rev/56becb6716fd changeset: 76652:56becb6716fd parent: 76650:e393d83d6877 parent: 76651:f23222d734bd user: Alexander Belopolsky date: Sun Apr 29 18:20:05 2012 -0400 summary: merged files: Lib/test/support.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -1106,12 +1106,16 @@ def run_with_tz(tz): def decorator(func): def inner(*args, **kwds): + try: + tzset = time.tzset + except AttributeError: + raise unittest.SkipTest("tzset required") if 'TZ' in os.environ: orig_tz = os.environ['TZ'] else: orig_tz = None os.environ['TZ'] = tz - time.tzset() + tzset() # now run the function, resetting the tz on exceptions try: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 00:53:57 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 30 Apr 2012 00:53:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314428=3A_Make_test?= =?utf8?q?=5Fprocess=5Ftime=5Fthreads=28=29_less_strict?= Message-ID: http://hg.python.org/cpython/rev/0bdf0727ee29 changeset: 76653:0bdf0727ee29 user: Victor Stinner date: Mon Apr 30 00:51:31 2012 +0200 summary: Issue #14428: Make test_process_time_threads() less strict files: Lib/test/test_time.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -438,7 +438,8 @@ t2 = time.process_time() thread.stop = True thread.join() - self.assertGreaterEqual(t2 - t1, busy) + # Use a factor of 0.75 because time.process_time() is maybe not precise + self.assertGreaterEqual(t2 - t1, busy * 0.75) @unittest.skipUnless(hasattr(time, 'monotonic'), 'need time.monotonic') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 01:40:57 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 30 Apr 2012 01:40:57 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314428=3A_Remove_te?= =?utf8?q?st=5Fprocess=5Ftime=5Fthreads=28=29_from_test=5Ftime?= Message-ID: http://hg.python.org/cpython/rev/ad3d6010379b changeset: 76654:ad3d6010379b user: Victor Stinner date: Mon Apr 30 01:39:57 2012 +0200 summary: Issue #14428: Remove test_process_time_threads() from test_time The test is unstable and it's not really interesting to test exactly how threads are handled. files: Lib/test/test_time.py | 52 ------------------------------- 1 files changed, 0 insertions(+), 52 deletions(-) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -389,58 +389,6 @@ self.assertEqual(info.is_monotonic, True) self.assertEqual(info.is_adjusted, False) - @unittest.skipUnless(threading, - 'need threading') - def test_process_time_threads(self): - def factorial(n): - if n >= 2: - return n * factorial(n-1) - else: - return 1 - - def use_cpu(n, loops): - for loop in range(loops): - factorial(n) - - class FactorialThread(threading.Thread): - def __init__(self, n, loops): - threading.Thread.__init__(self) - self.n = n - self.loops = loops - - def run(self): - use_cpu(self.n, self.loops) - - # Calibrate use_cpu() to use at least 1 ms of system time - n = 50 - loops = 1 - resolution = time.get_clock_info('process_time').resolution - min_rdt = max(resolution, 0.001) - while 1: - rt1 = time.time() - t1 = time.process_time() - use_cpu(n, loops) - t2 = time.process_time() - rt2 = time.time() - rdt = rt2 - rt1 - if rdt >= min_rdt: - break - loops *= 2 - busy = t2 - t1 - - # Ensure that time.process_time() includes the CPU time of all threads - thread = FactorialThread(n, loops) - t1 = time.process_time() - thread.start() - # Use sleep() instead of thread.join() because thread.join() time may - # be included in time.process_time() depending on its implementation - time.sleep(rdt * 2) - t2 = time.process_time() - thread.stop = True - thread.join() - # Use a factor of 0.75 because time.process_time() is maybe not precise - self.assertGreaterEqual(t2 - t1, busy * 0.75) - @unittest.skipUnless(hasattr(time, 'monotonic'), 'need time.monotonic') @unittest.skipUnless(hasattr(time, 'clock_settime'), -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 02:04:50 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Apr 2012 02:04:50 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_Phase_2_of_PEP_302_is_done=2E?= Message-ID: http://hg.python.org/peps/rev/f1b89efedc7e changeset: 4323:f1b89efedc7e parent: 4316:108e9e328481 user: Brett Cannon date: Sun Apr 29 20:04:31 2012 -0400 summary: Phase 2 of PEP 302 is done. files: pep-0302.txt | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-) diff --git a/pep-0302.txt b/pep-0302.txt --- a/pep-0302.txt +++ b/pep-0302.txt @@ -162,13 +162,7 @@ list is yet another new object in the sys.module: sys.meta_path. Currently, this list is empty by default, and frozen and built-in module imports are done after traversing sys.meta_path, but still - before sys.path. (Again, later we can add real frozen, built-in and - sys.path importer objects on sys.meta_path, allowing for some extra - flexibility, but this could be done as a "phase 2" project, possibly - for Python 2.4. It would be the finishing touch as then *every* - import would go through sys.meta_path, making it the central import - dispatcher.) - + before sys.path. Specification part 1: The Importer Protocol -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 30 02:04:51 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Apr 2012 02:04:51 +0200 Subject: [Python-checkins] =?utf8?q?peps_=28merge_default_-=3E_default=29?= =?utf8?q?=3A_merge?= Message-ID: http://hg.python.org/peps/rev/518e16177cce changeset: 4324:518e16177cce parent: 4323:f1b89efedc7e parent: 4322:a9a6a0851544 user: Brett Cannon date: Sun Apr 29 20:04:45 2012 -0400 summary: merge files: pep-0008.txt | 16 ++++++++----- pep-0418.txt | 46 ++++++++++++--------------------------- pep-0420.txt | 4 +- 3 files changed, 26 insertions(+), 40 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -841,16 +841,20 @@ whenever they do something other than acquire and release resources. For example: - Yes: with conn.begin_transaction(): + Yes:: + + with conn.begin_transaction(): do_stuff_in_transaction(conn) - No: with conn: + No:: + + with conn: do_stuff_in_transaction(conn) - The latter example doesn't provide any information to indicate that - the __enter__ and __exit__ methods are doing something other than - closing the connection after a transaction. Being explicit is - important in this case. + The latter example doesn't provide any information to indicate that + the __enter__ and __exit__ methods are doing something other than + closing the connection after a transaction. Being explicit is + important in this case. - Use string methods instead of the string module. diff --git a/pep-0418.txt b/pep-0418.txt --- a/pep-0418.txt +++ b/pep-0418.txt @@ -114,20 +114,15 @@ * ``"process_time"``: ``time.process_time()`` * ``"time"``: ``time.time()`` -Return a dictionary with the following keys: +Return a ``time.clock_info`` object which has the following attributes: -* Mandatory keys: - - * ``"implementation"`` (str): name of the underlying operating system - function. Examples: ``"QueryPerformanceCounter()"``, - ``"clock_gettime(CLOCK_REALTIME)"``. - * ``"resolution"`` (float): resolution in seconds of the clock. - * ``"is_monotonic"`` (bool): True if the clock cannot go backward. - -* Optional keys: - - * ``"is_adjusted"`` (bool): True if the clock is adjusted (e.g. by a - NTP daemon). + * ``implementation`` (str): name of the underlying operating system + function. Examples: ``"QueryPerformanceCounter()"``, + ``"clock_gettime(CLOCK_REALTIME)"``. + * ``is_monotonic`` (bool): True if the clock cannot go backward. + * ``is_adjusted`` (bool): True if the clock is adjusted (e.g. by a + NTP daemon). + * ``resolution`` (float): resolution in seconds of the clock. time.monotonic() @@ -610,14 +605,14 @@ :Clock: An instrument for measuring time. Different clocks have different - characteristics; for example, a clock with + characteristics; for example, a clock with nanosecond may start to after a few minutes, while a less precise clock remained accurate for days. This PEP is primarily concerned with clocks which use a unit of seconds. :Counter: A clock which increments each time a certain event occurs. A - counter is , but not . It can + counter is strictly monotonic, but not a monotonic clock. It can be used to generate a unique (and ordered) timestamp, but these timestamps cannot be mapped to ; tick creation may well be bursty, with several advances in the same millisecond followed @@ -630,12 +625,6 @@ when profiling, but they do not map directly to user response time, nor are they directly comparable to (real time) seconds. -:Duration: - Elapsed time. The difference between the starting and ending - times. A defined creates an implicit (and usually large) - duration. More precision can generally be provided for a - relatively small . - :Drift: The accumulated error against "true" time, as defined externally to the system. Drift may be due to imprecision, or to a difference @@ -657,12 +646,7 @@ Moving in at most one direction; for clocks, that direction is forward. The should also be , and should be convertible to a unit of seconds. The tradeoffs often include lack - of a defined or mapping to , and being more - expensive (in , power usage, or spent within - calls to the clock itself) to use. For example, the clock may - represent (a constant multiplied by) ticks of a specific quartz - timer on a specific CPU core, and calls would therefore require - synchronization between cores. + of a defined or mapping to . :Precision: The amount of deviation among measurements of the same physical @@ -968,11 +952,9 @@ based on absolute elapsed time since system boot. It is not adjusted and cannot be set. -mach_timebase_info() gives a fraction to convert the clock value to a -number of nanoseconds. According to the documentation (`Technical Q&A -QA1398 `_), -mach_timebase_info() is always equal to one and never fails, even if -the function may fail according to its prototype. +mach_timebase_info() gives a fraction to convert the clock value to a number of +nanoseconds. See also the `Technical Q&A QA1398 +`_. mach_absolute_time() stops during a sleep on a PowerPC CPU, but not on an Intel CPU: `Different behaviour of mach_absolute_time() on i386/ppc diff --git a/pep-0420.txt b/pep-0420.txt --- a/pep-0420.txt +++ b/pep-0420.txt @@ -122,8 +122,8 @@ * If not, but ``foo`` is found and is a directory, it is recorded. If the scan along the parent path completes without finding a module -or package, then a namespace package is created. The new namespace -package: +or package and at least one directory was recorded, then a namespace +package is created. The new namespace package: * Has a ``__file__`` attribute set to the first directory that was found during the scan, including the trailing path separator. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 30 02:59:47 2012 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Apr 2012 02:59:47 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Write_the_What=27s_New_for_?= =?utf8?q?the_importlib_stuff=2E?= Message-ID: http://hg.python.org/cpython/rev/add8b52db99b changeset: 76655:add8b52db99b user: Brett Cannon date: Sun Apr 29 20:59:41 2012 -0400 summary: Write the What's New for the importlib stuff. files: Doc/whatsnew/3.3.rst | 122 +++++++++++++++++++++++++++++++ 1 files changed, 122 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -452,6 +452,89 @@ '' +Using importlib as the Implementation of Import +=============================================== +:issue:`2377` - Replace __import__ w/ importlib.__import__ +:issue:`13959` - Re-implement parts of :mod:`imp` in pure Python +:issue:`14605` - Make import machinery explicit +:issue:`14646` - Require loaders set __loader__ and __package__ + +(Written by Brett Cannon) + +The :func:`__import__` function is now powered by :func:`importlib.__import__`. +This work leads to the completion of "phase 2" of :pep:`302`. There are +multiple benefits to this change. First, it has allowed for more of the +machinery powering import to be exposed instead of being implicit and hidden +within the C code. It also provides a single implementation for all Python VMs +supporting Python 3.3 to use, helping to end any VM-specific deviations in +import semantics. And finally it eases the maintenance of import, allowing for +future growth to occur. + +For the common user, this change should result in no visible change in +semantics. Any possible changes required in one's code to handle this change +should read the `Porting Python code`_ section of this document to see what +needs to be changed, but it will only affect those that currently manipulate +import or try calling it programmatically. + +New APIs +-------- +One of the large benefits of this work is the exposure of what goes into +making the import statement work. That means the various importers that were +once implicit are now fully exposed as part of the :mod:`importlib` package. + +In terms of finders, * :class:`importlib.machinery.FileFinder` exposes the +mechanism used to search for source and bytecode files of a module. Previously +this class was an implicit member of :attr:`sys.path_hooks`. + +For loaders, the new abstract base class :class:`importlib.abc.FileLoader` helps +write a loader that uses the file system as the storage mechanism for a module's +code. The loader for source files +(:class:`importlib.machinery.SourceFileLoader`), sourceless bytecode files +(:class:`importlib.machinery.SourcelessFileLoader`), and extension modules +(:class:`importlib.machinery.ExtensionFileLoader`) are now available for +direct use. + +:exc:`ImportError` now has ``name`` and ``path`` attributes which are set when +there is relevant data to provide. The message for failed imports will also +provide the full name of the module now instead of just the tail end of the +module's name. + +The :func:`importlib.invalidate_caches` function will now call the method with +the same name on all finders cached in :attr:`sys.path_importer_cache` to help +clean up any stored state as necessary. + +Visible Changes +--------------- +[For potential required changes to code, see the `Porting Python code`_ +section] + +Beyond the expanse of what :mod:`importlib` now exposes, there are other +visible changes to import. The biggest is that :attr:`sys.meta_path` and +:attr:`sys.path_hooks` now store all of the finders used by import explicitly. +Previously the finders were implicit and hidden within the C code of import +instead of being directly exposed. This means that one can now easily remove or +change the order of the various finders to fit one's needs. + +Another change is that all modules have a ``__loader__`` attribute, storing the +loader used to create the module. :pep:`302` has been updated to make this +attribute mandatory for loaders to implement, so in the future once 3rd-party +loaders have been updated people will be able to rely on the existence of the +attribute. Until such time, though, import is setting the module post-load. + +Loaders are also now expected to set the ``__package__`` attribute from +:pep:`366`. Once again, import itself is already setting this on all loaders +from :mod:`importlib` and import itself is setting the attribute post-load. + +``None`` is now inserted into :attr:`sys.path_importer_cache` when no finder +can be found on :attr:`sys.path_hooks`. Since :class:`imp.NullImporter` is not +directly exposed on :attr:`sys.path_hooks` it could no longer be relied upon to +always be available to use as a value representing no finder found. + +All other changes relate to semantic changes which should be taken into +consideration when updating code for Python 3.3, and thus should be read about +in the `Porting Python code`_ section of this document. + + Other Language Changes ====================== @@ -1283,6 +1366,45 @@ timestamp is out of range. :exc:`OSError` is now raised if C functions :c:func:`gmtime` or :c:func:`localtime` failed. +* The default finders used by import now utilize a cache of what is contained + within a specific directory. If you create a Python source file or sourceless + bytecode file, make sure to call :func:`importlib.invalidate_caches` to clear + out the cache for the finders to notice the new file. + +* :exc:`ImportError` now uses the full name of the module that was attemped to + be imported. Doctests that check ImportErrors' message will need to be + updated to use the full name of the module instead of just the tail of the + name. + +* The **index** argument to :func:`__import__` now defaults to 0 instead of -1 + and no longer support negative values. It was an oversight when :pep:`328` was + implemented that the default value remained -1. If you need to continue to + perform a relative import followed by an absolute import, then perform the + relative import using an index of 1, followed by another import using an + index of 0. It is preferred, though, that you use + :func:`importlib.import_module` rather than call :func:`__import__` directly. + +* :func:`__import__` no longer allows one to use an index value other than 0 + for top-level modules. E.g. ``__import__('sys', level=1)`` is now an error. + +* Because :attr:`sys.meta_path` and :attr:`sys.path_hooks` now have finders on + them by default, you will most likely want to use :meth:`list.insert` instead + of :meth:`list.append` to add to those lists. + +* Because ``None`` is now inserted into :attr:`sys.path_importer_cache`, if you + are clearing out entries in the dictionary of paths that do not have a + finder, you will need to remove keys paired with values of ``None`` **and** + :class:`imp.NullImporter` to be backwards-compatible. This will need to extra + overhead on older versions of Python that re-insert ``None`` into + :attr:`sys.path_importer_cache` where it repesents the use of implicit + finders, but semantically it should not change anything. + +* :meth:`importlib.abc.SourceLoader.path_mtime` is now deprecated in favour of + :meth:`importlib.abc.SourceLoader.path_stats` as bytecode files now store + both the modification time and size of the source file the bytecode file was + compiled from. + + Porting C code -------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 03:09:21 2012 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 30 Apr 2012 03:09:21 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Track_the_cache_size_direct?= =?utf8?b?bHku?= Message-ID: http://hg.python.org/cpython/rev/d4fd58fff480 changeset: 76656:d4fd58fff480 user: Raymond Hettinger date: Sun Apr 29 18:09:02 2012 -0700 summary: Track the cache size directly. files: Lib/functools.py | 21 +++++++++++---------- 1 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -168,15 +168,14 @@ # to allow the implementation to change (including a possible C version). # Constants shared by all lru cache instances: - kwd_mark = (object(),) # separate positional and keyword args - sentinel = object() # unique object used to signal cache misses - _len = len # localize the global len() function + kwd_mark = (object(),) # separate positional and keyword args + sentinel = object() # unique object used to signal cache misses PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields def decorating_function(user_function): cache = {} - hits = misses = 0 + hits = misses = currsize = 0 cache_get = cache.get # bound method to lookup a key or return None lock = Lock() # because linkedlist updates aren't threadsafe root = [] # root of the circular doubly linked list @@ -209,7 +208,7 @@ def wrapper(*args, **kwds): # simple caching without ordering or size limit - nonlocal hits, misses + nonlocal hits, misses, currsize key = make_key(args, kwds, typed) if kwds or typed else args result = cache_get(key, sentinel) if result is not sentinel: @@ -218,13 +217,14 @@ result = user_function(*args, **kwds) cache[key] = result misses += 1 + currsize += 1 return result else: def wrapper(*args, **kwds): # size limited caching that tracks accesses by recency - nonlocal root, hits, misses + nonlocal root, hits, misses, currsize key = make_key(args, kwds, typed) if kwds or typed else args with lock: link = cache_get(key) @@ -241,11 +241,12 @@ return result result = user_function(*args, **kwds) with lock: - if _len(cache) < maxsize: + if currsize < maxsize: # put result in a new link at the front of the queue last = root[PREV] link = [last, root, key, result] cache[key] = last[NEXT] = root[PREV] = link + currsize += 1 else: # use root to store the new key and result root[KEY] = key @@ -261,15 +262,15 @@ def cache_info(): """Report cache statistics""" with lock: - return _CacheInfo(hits, misses, maxsize, len(cache)) + return _CacheInfo(hits, misses, maxsize, currsize) def cache_clear(): """Clear the cache and cache statistics""" - nonlocal hits, misses + nonlocal hits, misses, currsize with lock: cache.clear() root[:] = [root, root, None, None] - hits = misses = 0 + hits = misses = currsize = 0 wrapper.cache_info = cache_info wrapper.cache_clear = cache_clear -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 03:27:38 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Apr 2012 03:27:38 +0200 Subject: [Python-checkins] =?utf8?q?peps=3A_fix_link?= Message-ID: http://hg.python.org/peps/rev/c3f2e2c4ebc2 changeset: 4325:c3f2e2c4ebc2 user: Benjamin Peterson date: Sun Apr 29 21:27:35 2012 -0400 summary: fix link files: pep-0415.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0415.txt b/pep-0415.txt --- a/pep-0415.txt +++ b/pep-0415.txt @@ -70,7 +70,7 @@ ========== .. _issue 14133: - http://bugs.python.org/issue6210 + http://bugs.python.org/issue14133 Copyright ========= -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Apr 30 05:25:19 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 30 Apr 2012 05:25:19 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314687=3A_Cleanup_P?= =?utf8?q?yUnicode=5FFormat=28=29?= Message-ID: http://hg.python.org/cpython/rev/42fbb4f9b540 changeset: 76657:42fbb4f9b540 parent: 76654:ad3d6010379b user: Victor Stinner date: Mon Apr 30 05:19:21 2012 +0200 summary: Issue #14687: Cleanup PyUnicode_Format() files: Objects/unicodeobject.c | 86 ++++++++++------------------ 1 files changed, 30 insertions(+), 56 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -6986,8 +6986,6 @@ v = PyUnicode_New(size, 127); if (v == NULL) goto onError; - if (size == 0) - return v; kind = PyUnicode_KIND(v); data = PyUnicode_DATA(v); outpos = 0; @@ -13856,20 +13854,22 @@ "incomplete format"); goto onError; } - if (c != '%') { - v = getnextarg(args, arglen, &argidx); - if (v == NULL) - goto onError; - } + + if (c == '%') { + _PyAccu_Accumulate(&acc, percent); + continue; + } + + + v = getnextarg(args, arglen, &argidx); + if (v == NULL) + goto onError; + sign = 0; fill = ' '; fillobj = blank; switch (c) { - case '%': - _PyAccu_Accumulate(&acc, percent); - continue; - case 's': case 'r': case 'a': @@ -13884,26 +13884,7 @@ temp = PyObject_Repr(v); else temp = PyObject_ASCII(v); - if (temp == NULL) - goto onError; - if (PyUnicode_Check(temp)) - /* nothing to do */; - else { - Py_DECREF(temp); - PyErr_SetString(PyExc_TypeError, - "%s argument has non-string str()"); - goto onError; - } - } - if (PyUnicode_READY(temp) == -1) { - Py_CLEAR(temp); - goto onError; - } - pbuf = PyUnicode_DATA(temp); - kind = PyUnicode_KIND(temp); - len = PyUnicode_GET_LENGTH(temp); - if (prec >= 0 && len > prec) - len = prec; + } break; case 'i': @@ -13926,18 +13907,9 @@ if (iobj!=NULL) { if (PyLong_Check(iobj)) { isnumok = 1; + sign = 1; temp = formatlong(iobj, flags, prec, (c == 'i'? 'd': c)); Py_DECREF(iobj); - if (!temp) - goto onError; - if (PyUnicode_READY(temp) == -1) { - Py_CLEAR(temp); - goto onError; - } - pbuf = PyUnicode_DATA(temp); - kind = PyUnicode_KIND(temp); - len = PyUnicode_GET_LENGTH(temp); - sign = 1; } else { Py_DECREF(iobj); @@ -13962,21 +13934,12 @@ case 'F': case 'g': case 'G': - temp = formatfloat(v, flags, prec, c); - if (!temp) - goto onError; - if (PyUnicode_READY(temp) == -1) { - Py_CLEAR(temp); - goto onError; - } - pbuf = PyUnicode_DATA(temp); - kind = PyUnicode_KIND(temp); - len = PyUnicode_GET_LENGTH(temp); sign = 1; if (flags & F_ZERO) { fill = '0'; fillobj = zero; } + temp = formatfloat(v, flags, prec, c); break; case 'c': @@ -13985,11 +13948,6 @@ if (ch == (Py_UCS4) -1) goto onError; temp = _PyUnicode_FromUCS4(&ch, 1); - if (temp == NULL) - goto onError; - pbuf = PyUnicode_DATA(temp); - kind = PyUnicode_KIND(temp); - len = PyUnicode_GET_LENGTH(temp); break; } @@ -14002,6 +13960,22 @@ fmtpos - 1); goto onError; } + if (temp == NULL) + goto onError; + assert (PyUnicode_Check(temp)); + if (PyUnicode_READY(temp) == -1) { + Py_CLEAR(temp); + goto onError; + } + kind = PyUnicode_KIND(temp); + pbuf = PyUnicode_DATA(temp); + len = PyUnicode_GET_LENGTH(temp); + + if (c == 's' || c == 'r' || c == 'a') { + if (prec >= 0 && len > prec) + len = prec; + } + /* pbuf is initialized here. */ pindex = 0; if (sign) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 05:25:20 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 30 Apr 2012 05:25:20 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314687=3A_Avoid_an_?= =?utf8?q?useless_duplicated_string_in_PyUnicode=5FFormat=28=29?= Message-ID: http://hg.python.org/cpython/rev/08b54c635586 changeset: 76658:08b54c635586 user: Victor Stinner date: Mon Apr 30 05:21:52 2012 +0200 summary: Issue #14687: Avoid an useless duplicated string in PyUnicode_Format() files: Objects/unicodeobject.c | 22 +++++++++------------- 1 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -14051,20 +14051,16 @@ } } /* Copy all characters, preserving len */ - if (temp != NULL) { - assert(pbuf == PyUnicode_DATA(temp)); + if (pindex == 0 && len == PyUnicode_GET_LENGTH(temp)) { + r = _PyAccu_Accumulate(&acc, temp); + } + else { v = PyUnicode_Substring(temp, pindex, pindex + len); - } - else { - const char *p = (const char *) pbuf; - assert(pbuf != NULL); - p += kind * pindex; - v = PyUnicode_FromKindAndData(kind, p, len); - } - if (v == NULL) - goto onError; - r = _PyAccu_Accumulate(&acc, v); - Py_DECREF(v); + if (v == NULL) + goto onError; + r = _PyAccu_Accumulate(&acc, v); + Py_DECREF(v); + } if (r) goto onError; if (width > len && repeat_accumulate(&acc, blank, width - len)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 05:25:22 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 30 Apr 2012 05:25:22 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_default_-=3E_default?= =?utf8?q?=29=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/7319430a291d changeset: 76659:7319430a291d parent: 76658:08b54c635586 parent: 76656:d4fd58fff480 user: Victor Stinner date: Mon Apr 30 05:24:04 2012 +0200 summary: merge files: Doc/whatsnew/3.3.rst | 122 +++++++++++++++++++++++++++++++ Lib/functools.py | 21 ++-- 2 files changed, 133 insertions(+), 10 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -452,6 +452,89 @@ '' +Using importlib as the Implementation of Import +=============================================== +:issue:`2377` - Replace __import__ w/ importlib.__import__ +:issue:`13959` - Re-implement parts of :mod:`imp` in pure Python +:issue:`14605` - Make import machinery explicit +:issue:`14646` - Require loaders set __loader__ and __package__ + +(Written by Brett Cannon) + +The :func:`__import__` function is now powered by :func:`importlib.__import__`. +This work leads to the completion of "phase 2" of :pep:`302`. There are +multiple benefits to this change. First, it has allowed for more of the +machinery powering import to be exposed instead of being implicit and hidden +within the C code. It also provides a single implementation for all Python VMs +supporting Python 3.3 to use, helping to end any VM-specific deviations in +import semantics. And finally it eases the maintenance of import, allowing for +future growth to occur. + +For the common user, this change should result in no visible change in +semantics. Any possible changes required in one's code to handle this change +should read the `Porting Python code`_ section of this document to see what +needs to be changed, but it will only affect those that currently manipulate +import or try calling it programmatically. + +New APIs +-------- +One of the large benefits of this work is the exposure of what goes into +making the import statement work. That means the various importers that were +once implicit are now fully exposed as part of the :mod:`importlib` package. + +In terms of finders, * :class:`importlib.machinery.FileFinder` exposes the +mechanism used to search for source and bytecode files of a module. Previously +this class was an implicit member of :attr:`sys.path_hooks`. + +For loaders, the new abstract base class :class:`importlib.abc.FileLoader` helps +write a loader that uses the file system as the storage mechanism for a module's +code. The loader for source files +(:class:`importlib.machinery.SourceFileLoader`), sourceless bytecode files +(:class:`importlib.machinery.SourcelessFileLoader`), and extension modules +(:class:`importlib.machinery.ExtensionFileLoader`) are now available for +direct use. + +:exc:`ImportError` now has ``name`` and ``path`` attributes which are set when +there is relevant data to provide. The message for failed imports will also +provide the full name of the module now instead of just the tail end of the +module's name. + +The :func:`importlib.invalidate_caches` function will now call the method with +the same name on all finders cached in :attr:`sys.path_importer_cache` to help +clean up any stored state as necessary. + +Visible Changes +--------------- +[For potential required changes to code, see the `Porting Python code`_ +section] + +Beyond the expanse of what :mod:`importlib` now exposes, there are other +visible changes to import. The biggest is that :attr:`sys.meta_path` and +:attr:`sys.path_hooks` now store all of the finders used by import explicitly. +Previously the finders were implicit and hidden within the C code of import +instead of being directly exposed. This means that one can now easily remove or +change the order of the various finders to fit one's needs. + +Another change is that all modules have a ``__loader__`` attribute, storing the +loader used to create the module. :pep:`302` has been updated to make this +attribute mandatory for loaders to implement, so in the future once 3rd-party +loaders have been updated people will be able to rely on the existence of the +attribute. Until such time, though, import is setting the module post-load. + +Loaders are also now expected to set the ``__package__`` attribute from +:pep:`366`. Once again, import itself is already setting this on all loaders +from :mod:`importlib` and import itself is setting the attribute post-load. + +``None`` is now inserted into :attr:`sys.path_importer_cache` when no finder +can be found on :attr:`sys.path_hooks`. Since :class:`imp.NullImporter` is not +directly exposed on :attr:`sys.path_hooks` it could no longer be relied upon to +always be available to use as a value representing no finder found. + +All other changes relate to semantic changes which should be taken into +consideration when updating code for Python 3.3, and thus should be read about +in the `Porting Python code`_ section of this document. + + Other Language Changes ====================== @@ -1283,6 +1366,45 @@ timestamp is out of range. :exc:`OSError` is now raised if C functions :c:func:`gmtime` or :c:func:`localtime` failed. +* The default finders used by import now utilize a cache of what is contained + within a specific directory. If you create a Python source file or sourceless + bytecode file, make sure to call :func:`importlib.invalidate_caches` to clear + out the cache for the finders to notice the new file. + +* :exc:`ImportError` now uses the full name of the module that was attemped to + be imported. Doctests that check ImportErrors' message will need to be + updated to use the full name of the module instead of just the tail of the + name. + +* The **index** argument to :func:`__import__` now defaults to 0 instead of -1 + and no longer support negative values. It was an oversight when :pep:`328` was + implemented that the default value remained -1. If you need to continue to + perform a relative import followed by an absolute import, then perform the + relative import using an index of 1, followed by another import using an + index of 0. It is preferred, though, that you use + :func:`importlib.import_module` rather than call :func:`__import__` directly. + +* :func:`__import__` no longer allows one to use an index value other than 0 + for top-level modules. E.g. ``__import__('sys', level=1)`` is now an error. + +* Because :attr:`sys.meta_path` and :attr:`sys.path_hooks` now have finders on + them by default, you will most likely want to use :meth:`list.insert` instead + of :meth:`list.append` to add to those lists. + +* Because ``None`` is now inserted into :attr:`sys.path_importer_cache`, if you + are clearing out entries in the dictionary of paths that do not have a + finder, you will need to remove keys paired with values of ``None`` **and** + :class:`imp.NullImporter` to be backwards-compatible. This will need to extra + overhead on older versions of Python that re-insert ``None`` into + :attr:`sys.path_importer_cache` where it repesents the use of implicit + finders, but semantically it should not change anything. + +* :meth:`importlib.abc.SourceLoader.path_mtime` is now deprecated in favour of + :meth:`importlib.abc.SourceLoader.path_stats` as bytecode files now store + both the modification time and size of the source file the bytecode file was + compiled from. + + Porting C code -------------- diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -168,15 +168,14 @@ # to allow the implementation to change (including a possible C version). # Constants shared by all lru cache instances: - kwd_mark = (object(),) # separate positional and keyword args - sentinel = object() # unique object used to signal cache misses - _len = len # localize the global len() function + kwd_mark = (object(),) # separate positional and keyword args + sentinel = object() # unique object used to signal cache misses PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields def decorating_function(user_function): cache = {} - hits = misses = 0 + hits = misses = currsize = 0 cache_get = cache.get # bound method to lookup a key or return None lock = Lock() # because linkedlist updates aren't threadsafe root = [] # root of the circular doubly linked list @@ -209,7 +208,7 @@ def wrapper(*args, **kwds): # simple caching without ordering or size limit - nonlocal hits, misses + nonlocal hits, misses, currsize key = make_key(args, kwds, typed) if kwds or typed else args result = cache_get(key, sentinel) if result is not sentinel: @@ -218,13 +217,14 @@ result = user_function(*args, **kwds) cache[key] = result misses += 1 + currsize += 1 return result else: def wrapper(*args, **kwds): # size limited caching that tracks accesses by recency - nonlocal root, hits, misses + nonlocal root, hits, misses, currsize key = make_key(args, kwds, typed) if kwds or typed else args with lock: link = cache_get(key) @@ -241,11 +241,12 @@ return result result = user_function(*args, **kwds) with lock: - if _len(cache) < maxsize: + if currsize < maxsize: # put result in a new link at the front of the queue last = root[PREV] link = [last, root, key, result] cache[key] = last[NEXT] = root[PREV] = link + currsize += 1 else: # use root to store the new key and result root[KEY] = key @@ -261,15 +262,15 @@ def cache_info(): """Report cache statistics""" with lock: - return _CacheInfo(hits, misses, maxsize, len(cache)) + return _CacheInfo(hits, misses, maxsize, currsize) def cache_clear(): """Clear the cache and cache statistics""" - nonlocal hits, misses + nonlocal hits, misses, currsize with lock: cache.clear() root[:] = [root, root, None, None] - hits = misses = 0 + hits = misses = currsize = 0 wrapper.cache_info = cache_info wrapper.cache_clear = cache_clear -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Apr 30 05:40:09 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 30 Apr 2012 05:40:09 +0200 Subject: [Python-checkins] Daily reference leaks (d4fd58fff480): sum=0 Message-ID: results for d4fd58fff480 on branch "default" -------------------------------------------- test_support leaked [0, -1, 1] references, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogkVmW2m', '-x'] From python-checkins at python.org Mon Apr 30 06:28:43 2012 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 30 Apr 2012 06:28:43 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0NDMz?= =?utf8?q?=3A_Prevent_msvcrt_crash_in_interactive_prompt_when_stdin_is_clo?= =?utf8?q?sed=2E?= Message-ID: http://hg.python.org/cpython/rev/2de5e9715fe9 changeset: 76660:2de5e9715fe9 branch: 3.2 parent: 76651:f23222d734bd user: Martin v. L?wis date: Mon Apr 30 06:10:41 2012 +0200 summary: Issue #14433: Prevent msvcrt crash in interactive prompt when stdin is closed. files: Misc/NEWS | 3 +++ Parser/myreadline.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14433: Prevent msvcrt crash in interactive prompt when stdin + is closed. + - Issue #11603 (again): Setting __repr__ to __str__ now raises a RuntimeError when repr() or str() is called on such an object. diff --git a/Parser/myreadline.c b/Parser/myreadline.c --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -42,7 +42,10 @@ (void)(PyOS_InputHook)(); errno = 0; clearerr(fp); - p = fgets(buf, len, fp); + if (_PyVerify_fd(fileno(fp))) + p = fgets(buf, len, fp); + else + p = NULL; if (p != NULL) return 0; /* No error */ err = errno; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 06:28:44 2012 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 30 Apr 2012 06:28:44 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Merge_with_3=2E2=3A_issue_=2314433?= Message-ID: http://hg.python.org/cpython/rev/2c27093fd11f changeset: 76661:2c27093fd11f parent: 76659:7319430a291d parent: 76660:2de5e9715fe9 user: Martin v. L?wis date: Mon Apr 30 06:20:37 2012 +0200 summary: Merge with 3.2: issue #14433 files: Misc/NEWS | 3 +++ Parser/myreadline.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #14433: Prevent msvcrt crash in interactive prompt when stdin + is closed. + - Issue #14521: Make result of float('nan') and float('-nan') more consistent across platforms. diff --git a/Parser/myreadline.c b/Parser/myreadline.c --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -42,7 +42,10 @@ (void)(PyOS_InputHook)(); errno = 0; clearerr(fp); - p = fgets(buf, len, fp); + if (_PyVerify_fd(fileno(fp))) + p = fgets(buf, len, fp); + else + p = NULL; if (p != NULL) return 0; /* No error */ err = errno; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 12:50:06 2012 From: python-checkins at python.org (georg.brandl) Date: Mon, 30 Apr 2012 12:50:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Review_of_doc_changes_re_PE?= =?utf8?q?P_418=2E?= Message-ID: http://hg.python.org/cpython/rev/31715c80b8d8 changeset: 76662:31715c80b8d8 user: Georg Brandl date: Mon Apr 30 12:50:30 2012 +0200 summary: Review of doc changes re PEP 418. files: Doc/library/time.rst | 70 ++++++++++++++++---------------- 1 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -162,24 +162,24 @@ .. class:: clock_info - Clock information object created by :func:`get_clock_info`. + Clock information object returned by :func:`get_clock_info`. .. attribute:: implementation - name of the underlying C function used to get the clock value + The name of the underlying C function used to get the clock value. .. attribute:: is_monotonic - ``True`` if the clock cannot go backward, ``False`` otherwise + ``True`` if the clock cannot go backward, ``False`` otherwise. .. attribute:: is_adjusted - ``True`` if the clock can be adjusted (e.g. by a NTP daemon), - ``False`` otherwise + ``True`` if the clock can be adjusted (e.g. by a NTP daemon), ``False`` + otherwise. .. attribute:: resolution - Resolution of the clock in seconds (:class:`float`) + The resolution of the clock in seconds (:class:`float`). .. versionadded:: 3.3 @@ -196,7 +196,7 @@ .. data:: CLOCK_HIGHRES The Solaris OS has a CLOCK_HIGHRES timer that attempts to use an optimal - hardware source, and may give close to nanosecond resolution. CLOCK_HIGHRES + hardware source, and may give close to nanosecond resolution. CLOCK_HIGHRES is the nonadjustable, high-resolution clock. Availability: Solaris. @@ -206,8 +206,8 @@ .. data:: CLOCK_MONOTONIC - Clock that cannot be set and represents monotonic time since some - unspecified starting point. + Clock that cannot be set and represents monotonic time since some unspecified + starting point. Availability: Unix. @@ -235,7 +235,7 @@ .. data:: CLOCK_REALTIME - System-wide real-time clock. Setting this clock requires appropriate + System-wide real-time clock. Setting this clock requires appropriate privileges. Availability: Unix. @@ -268,15 +268,14 @@ .. function:: get_clock_info(name) Get information on the specified clock as a :class:`clock_info` object. + Supported clock names and the corresponding functions to read their value + are: - Supported clock names: - - - * ``'clock'``: :func:`time.clock` - * ``'monotonic'``: :func:`time.monotonic` - * ``'perf_counter'``: :func:`time.perf_counter` - * ``'process_time'``: :func:`time.process_time` - * ``'time'``: :func:`time.time` + * ``'clock'``: :func:`time.clock` + * ``'monotonic'``: :func:`time.monotonic` + * ``'perf_counter'``: :func:`time.perf_counter` + * ``'process_time'``: :func:`time.process_time` + * ``'time'``: :func:`time.time` .. versionadded:: 3.3 @@ -312,16 +311,16 @@ .. function:: monotonic() - Monotonic clock, i.e. cannot go backward. It is not affected by system - clock updates. The reference point of the returned value is undefined, so - that only the difference between the results of consecutive calls is valid - and is a number of seconds. + Return the value (in fractional seconds) of a monotonic clock, i.e. a clock + that cannot go backwards. The clock is not affected by system clock updates. + The reference point of the returned value is undefined, so that only the + difference between the results of consecutive calls is valid. On Windows versions older than Vista, :func:`monotonic` detects - :c:func:`GetTickCount` integer overflow (32 bits, roll-over after 49.7 - days). It increases an internal epoch (reference time by) 2\ :sup:`32` each - time that an overflow is detected. The epoch is stored in the process-local - state and so the value of :func:`monotonic` may be different in two Python + :c:func:`GetTickCount` integer overflow (32 bits, roll-over after 49.7 days). + It increases an internal epoch (reference time by) 2\ :sup:`32` each time + that an overflow is detected. The epoch is stored in the process-local state + and so the value of :func:`monotonic` may be different in two Python processes running for more than 49 days. On more recent versions of Windows and on other operating systems, :func:`monotonic` is system-wide. @@ -332,21 +331,22 @@ .. function:: perf_counter() - Performance counter with the highest available resolution to measure a short - duration. It does include time elapsed during sleep and is system-wide. - The reference point of the returned value is undefined, so that only the - difference between the results of consecutive calls is valid and is a number - of seconds. + Return the value (in fractional seconds) of a performance counter, i.e. a + clock with the highest available resolution to measure a short duration. It + does include time elapsed during sleep and is system-wide. The reference + point of the returned value is undefined, so that only the difference between + the results of consecutive calls is valid. .. versionadded:: 3.3 .. function:: process_time() - Sum of the system and user CPU time of the current process. It does not - include time elapsed during sleep. It is process-wide by definition. The - reference point of the returned value is undefined, so that only the - difference between the results of consecutive calls is valid. + Return the value (in fractional seconds) of the sum of the system and user + CPU time of the current process. It does not include time elapsed during + sleep. It is process-wide by definition. The reference point of the + returned value is undefined, so that only the difference between the results + of consecutive calls is valid. .. versionadded:: 3.3 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 13:20:56 2012 From: python-checkins at python.org (richard.oudkerk) Date: Mon, 30 Apr 2012 13:20:56 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Mark_multiprocessing_files_?= =?utf8?q?with_=22Licensed_to_PSF_under_a_Contributor_Agreement=22?= Message-ID: http://hg.python.org/cpython/rev/25cc0c8fd4e2 changeset: 76663:25cc0c8fd4e2 user: Richard Oudkerk date: Mon Apr 30 12:13:55 2012 +0100 summary: Mark multiprocessing files with "Licensed to PSF under a Contributor Agreement" instead of BSD licence. files: Lib/multiprocessing/__init__.py | 27 +--------- Lib/multiprocessing/connection.py | 27 +--------- Lib/multiprocessing/forking.py | 27 +--------- Lib/multiprocessing/heap.py | 27 +--------- Lib/multiprocessing/managers.py | 27 +--------- Lib/multiprocessing/pool.py | 27 +--------- Lib/multiprocessing/process.py | 27 +--------- Lib/multiprocessing/queues.py | 27 +--------- Lib/multiprocessing/reduction.py | 27 +--------- Lib/multiprocessing/sharedctypes.py | 27 +--------- Lib/multiprocessing/synchronize.py | 27 +--------- Lib/multiprocessing/util.py | 27 +--------- Modules/_multiprocessing/multiprocessing.c | 3 +- Modules/_multiprocessing/semaphore.c | 3 +- 14 files changed, 16 insertions(+), 314 deletions(-) diff --git a/Lib/multiprocessing/__init__.py b/Lib/multiprocessing/__init__.py --- a/Lib/multiprocessing/__init__.py +++ b/Lib/multiprocessing/__init__.py @@ -13,32 +13,7 @@ # # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # __version__ = '0.70a1' diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -4,32 +4,7 @@ # multiprocessing/connection.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # __all__ = [ 'Client', 'Listener', 'Pipe', 'wait' ] diff --git a/Lib/multiprocessing/forking.py b/Lib/multiprocessing/forking.py --- a/Lib/multiprocessing/forking.py +++ b/Lib/multiprocessing/forking.py @@ -4,32 +4,7 @@ # multiprocessing/forking.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # import os diff --git a/Lib/multiprocessing/heap.py b/Lib/multiprocessing/heap.py --- a/Lib/multiprocessing/heap.py +++ b/Lib/multiprocessing/heap.py @@ -4,32 +4,7 @@ # multiprocessing/heap.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # import bisect diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -5,32 +5,7 @@ # multiprocessing/managers.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # __all__ = [ 'BaseManager', 'SyncManager', 'BaseProxy', 'Token' ] diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py --- a/Lib/multiprocessing/pool.py +++ b/Lib/multiprocessing/pool.py @@ -4,32 +4,7 @@ # multiprocessing/pool.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # __all__ = ['Pool'] diff --git a/Lib/multiprocessing/process.py b/Lib/multiprocessing/process.py --- a/Lib/multiprocessing/process.py +++ b/Lib/multiprocessing/process.py @@ -4,32 +4,7 @@ # multiprocessing/process.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # __all__ = ['Process', 'current_process', 'active_children'] diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -4,32 +4,7 @@ # multiprocessing/queues.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # __all__ = ['Queue', 'SimpleQueue', 'JoinableQueue'] diff --git a/Lib/multiprocessing/reduction.py b/Lib/multiprocessing/reduction.py --- a/Lib/multiprocessing/reduction.py +++ b/Lib/multiprocessing/reduction.py @@ -5,32 +5,7 @@ # multiprocessing/reduction.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # __all__ = ['reduce_socket', 'reduce_connection', 'send_handle', 'recv_handle'] diff --git a/Lib/multiprocessing/sharedctypes.py b/Lib/multiprocessing/sharedctypes.py --- a/Lib/multiprocessing/sharedctypes.py +++ b/Lib/multiprocessing/sharedctypes.py @@ -4,32 +4,7 @@ # multiprocessing/sharedctypes.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # import ctypes diff --git a/Lib/multiprocessing/synchronize.py b/Lib/multiprocessing/synchronize.py --- a/Lib/multiprocessing/synchronize.py +++ b/Lib/multiprocessing/synchronize.py @@ -4,32 +4,7 @@ # multiprocessing/synchronize.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # __all__ = [ diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -4,32 +4,7 @@ # multiprocessing/util.py # # Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. +# Licensed to PSF under a Contributor Agreement. # import functools diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -3,7 +3,8 @@ * * multiprocessing.c * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt + * Copyright (c) 2006-2008, R Oudkerk + * Licensed to PSF under a Contributor Agreement. */ #include "multiprocessing.h" diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -3,7 +3,8 @@ * * semaphore.c * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt + * Copyright (c) 2006-2008, R Oudkerk + * Licensed to PSF under a Contributor Agreement. */ #include "multiprocessing.h" -- Repository URL: http://hg.python.org/cpython From senthil at uthcode.com Mon Apr 30 14:12:58 2012 From: senthil at uthcode.com (Senthil Kumaran) Date: Mon, 30 Apr 2012 20:12:58 +0800 Subject: [Python-checkins] cpython (3.2): #14236: fix docs for \S. In-Reply-To: References: Message-ID: <20120430121258.GB3102@mathmagic> On Sun, Apr 29, 2012 at 12:37:25PM +0200, ezio.melotti wrote: > range of Unicode whitespace characters. > - \S Matches any non-whitespace character; equiv. to [^ \t\n\r\f\v]. > + \S Matches any non-whitespace character; equivalent to [^\s]. Is this correct? While I understand what meant (or implied) \s is not a valid ascii character in the documentation we denoted the sets using ascii characters only. -- Senthil From python-checkins at python.org Mon Apr 30 15:53:06 2012 From: python-checkins at python.org (richard.oudkerk) Date: Mon, 30 Apr 2012 15:53:06 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Minor_fix_for_multiprocessi?= =?utf8?q?ng_unit_test?= Message-ID: http://hg.python.org/cpython/rev/aff7bb5811c3 changeset: 76664:aff7bb5811c3 user: Richard Oudkerk date: Mon Apr 30 14:48:50 2012 +0100 summary: Minor fix for multiprocessing unit test Read from socket might have returned partial message. files: Lib/test/test_multiprocessing.py | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2034,7 +2034,14 @@ address = lconn.recv() rconn.send((address, msg)) new_conn = lconn.recv() - self.assertEqual(new_conn.recv(100), msg.upper()) + buf = [] + while True: + s = new_conn.recv(100) + if not s: + break + buf.append(s) + buf = b''.join(buf) + self.assertEqual(buf, msg.upper()) new_conn.close() lconn.send(None) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 15:53:07 2012 From: python-checkins at python.org (richard.oudkerk) Date: Mon, 30 Apr 2012 15:53:07 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_Issue_=2314669=3A_Skip_mult?= =?utf8?q?iprocessing_connection_pickling_test_on_MacOSX?= Message-ID: http://hg.python.org/cpython/rev/e64bec91ac91 changeset: 76665:e64bec91ac91 user: Richard Oudkerk date: Mon Apr 30 14:48:51 2012 +0100 summary: Issue #14669: Skip multiprocessing connection pickling test on MacOSX Passing of fds is unreliable on MacOSX, compare issues #6560 and #12958. files: Lib/test/test_multiprocessing.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -1960,6 +1960,8 @@ # Test of sending connection and socket objects between processes # +# Intermittent fails on Mac OS X -- see Issue14669 and Issue12958 + at unittest.skipIf(sys.platform == "darwin", "fd passing unreliable on Mac OS X") @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction") class _TestPicklingConnections(BaseTestCase): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 16:23:52 2012 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Apr 2012 16:23:52 +0200 Subject: [Python-checkins] =?utf8?q?cpython=3A_change_insertdict_to_not_st?= =?utf8?q?eal_references_=28=2313903=29?= Message-ID: http://hg.python.org/cpython/rev/c5fd332e5857 changeset: 76666:c5fd332e5857 user: Benjamin Peterson date: Mon Apr 30 10:23:40 2012 -0400 summary: change insertdict to not steal references (#13903) files: Objects/dictobject.c | 16 +++------------- 1 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -775,7 +775,6 @@ /* Internal routine to insert a new item into the table. Used both by the internal resize routine and by the public insert routine. -Eats a reference to key and one to value. Returns -1 if an error occurred, or 0 on success. */ static int @@ -793,20 +792,19 @@ ep = mp->ma_keys->dk_lookup(mp, key, hash, &value_addr); if (ep == NULL) { - Py_DECREF(key); - Py_DECREF(value); return -1; } + Py_INCREF(value); MAINTAIN_TRACKING(mp, key, value); old_value = *value_addr; if (old_value != NULL) { assert(ep->me_key != NULL && ep->me_key != dummy); *value_addr = value; Py_DECREF(old_value); /* which **CAN** re-enter */ - Py_DECREF(key); } else { if (ep->me_key == NULL) { + Py_INCREF(key); if (mp->ma_keys->dk_usable <= 0) { /* Need to resize. */ if (insertion_resize(mp) < 0) { @@ -823,11 +821,11 @@ } else { if (ep->me_key == dummy) { + Py_INCREF(key); ep->me_key = key; ep->me_hash = hash; Py_DECREF(dummy); } else { - Py_DECREF(key); assert(_PyDict_HasSplitTable(mp)); } } @@ -1184,8 +1182,6 @@ if (hash == -1) return -1; } - Py_INCREF(value); - Py_INCREF(key); /* insertdict() handles any resizing that might be necessary */ return insertdict(mp, key, hash, value); @@ -1702,8 +1698,6 @@ } while (_PyDict_Next(seq, &pos, &key, &oldvalue, &hash)) { - Py_INCREF(key); - Py_INCREF(value); if (insertdict(mp, key, hash, value)) { Py_DECREF(d); return NULL; @@ -1724,8 +1718,6 @@ } while (_PySet_NextEntry(seq, &pos, &key, &hash)) { - Py_INCREF(key); - Py_INCREF(value); if (insertdict(mp, key, hash, value)) { Py_DECREF(d); return NULL; @@ -1932,8 +1924,6 @@ if (value != NULL && (override || PyDict_GetItem(a, entry->me_key) == NULL)) { - Py_INCREF(entry->me_key); - Py_INCREF(value); if (insertdict(mp, entry->me_key, entry->me_hash, value) != 0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 16:43:58 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 30 Apr 2012 16:43:58 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=283=2E2=29=3A_Issue11352_-_Up?= =?utf8?q?date_cgi_module_docs?= Message-ID: http://hg.python.org/cpython/rev/a54b6e321f1c changeset: 76667:a54b6e321f1c branch: 3.2 parent: 76660:2de5e9715fe9 user: Senthil Kumaran date: Mon Apr 30 22:43:13 2012 +0800 summary: Issue11352 - Update cgi module docs files: Doc/library/cgi.rst | 17 ++++++++++------- 1 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst --- a/Doc/library/cgi.rst +++ b/Doc/library/cgi.rst @@ -86,11 +86,14 @@ tracking down bugs. You can always remove the ``cgitb`` line later when you have tested your script and are confident that it works correctly. -To get at submitted form data, use the :class:`FieldStorage` class. Instantiate -it exactly once, without arguments. This reads the form contents from standard -input or the environment (depending on the value of various environment -variables set according to the CGI standard). Since it may consume standard -input, it should be instantiated only once. +To get at submitted form data, use the :class:`FieldStorage` class. If the form +contains non-ASCII characters, use the *encoding* keyword parameter set to the +value of the encoding defined for the document. It is usually contained in the +META tag in the HEAD section of the HTML document or by the +:mailheader:`Content-Type` header). This reads the form contents from the +standard input or the environment (depending on the value of various +environment variables set according to the CGI standard). Since it may consume +standard input, it should be instantiated only once. The :class:`FieldStorage` instance can be indexed like a Python dictionary. It allows membership testing with the :keyword:`in` operator, and also supports @@ -136,10 +139,10 @@ If a field represents an uploaded file, accessing the value via the :attr:`value` attribute or the :func:`getvalue` method reads the entire file in -memory as a string. This may not be what you want. You can test for an uploaded +memory as bytes. This may not be what you want. You can test for an uploaded file by testing either the :attr:`filename` attribute or the :attr:`!file` attribute. You can then read the data at leisure from the :attr:`!file` -attribute:: +attribute (the :func:`read` and :func:`readline` methods will return bytes):: fileitem = form["userfile"] if fileitem.file: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 16:43:59 2012 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 30 Apr 2012 16:43:59 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue11352_-_Update_cgi_module_docs?= Message-ID: http://hg.python.org/cpython/rev/910a4b12c796 changeset: 76668:910a4b12c796 parent: 76666:c5fd332e5857 parent: 76667:a54b6e321f1c user: Senthil Kumaran date: Mon Apr 30 22:43:46 2012 +0800 summary: Issue11352 - Update cgi module docs files: Doc/library/cgi.rst | 17 ++++++++++------- 1 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst --- a/Doc/library/cgi.rst +++ b/Doc/library/cgi.rst @@ -86,11 +86,14 @@ tracking down bugs. You can always remove the ``cgitb`` line later when you have tested your script and are confident that it works correctly. -To get at submitted form data, use the :class:`FieldStorage` class. Instantiate -it exactly once, without arguments. This reads the form contents from standard -input or the environment (depending on the value of various environment -variables set according to the CGI standard). Since it may consume standard -input, it should be instantiated only once. +To get at submitted form data, use the :class:`FieldStorage` class. If the form +contains non-ASCII characters, use the *encoding* keyword parameter set to the +value of the encoding defined for the document. It is usually contained in the +META tag in the HEAD section of the HTML document or by the +:mailheader:`Content-Type` header). This reads the form contents from the +standard input or the environment (depending on the value of various +environment variables set according to the CGI standard). Since it may consume +standard input, it should be instantiated only once. The :class:`FieldStorage` instance can be indexed like a Python dictionary. It allows membership testing with the :keyword:`in` operator, and also supports @@ -136,10 +139,10 @@ If a field represents an uploaded file, accessing the value via the :attr:`value` attribute or the :func:`getvalue` method reads the entire file in -memory as a string. This may not be what you want. You can test for an uploaded +memory as bytes. This may not be what you want. You can test for an uploaded file by testing either the :attr:`filename` attribute or the :attr:`!file` attribute. You can then read the data at leisure from the :attr:`!file` -attribute:: +attribute (the :func:`read` and :func:`readline` methods will return bytes):: fileitem = form["userfile"] if fileitem.file: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 18:11:21 2012 From: python-checkins at python.org (ezio.melotti) Date: Mon, 30 Apr 2012 18:11:21 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogIzE0NTU4OiBkb2N1?= =?utf8?q?ment_the_module=2C_argv=2C_and_testLoader_args_of_unittest=2Emai?= =?utf8?q?n=2E?= Message-ID: http://hg.python.org/cpython/rev/55b2258c1c7c changeset: 76669:55b2258c1c7c branch: 2.7 parent: 76630:5bad73fbf593 user: Ezio Melotti date: Mon Apr 30 19:05:57 2012 +0300 summary: #14558: document the module, argv, and testLoader args of unittest.main. files: Doc/library/unittest.rst | 22 +++++++++++++++------- 1 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1784,11 +1784,12 @@ stream, descriptions, verbosity -.. function:: main([module[, defaultTest[, argv[, testRunner[, testLoader[, exit[, verbosity[, failfast[, catchbreak[,buffer]]]]]]]]]]) - - A command-line program that runs a set of tests; this is primarily for making - test modules conveniently executable. The simplest use for this function is to - include the following line at the end of a test script:: +.. function:: main([module[, defaultTest[, argv[, testRunner[, testLoader[, exit[, verbosity[, failfast[, catchbreak[, buffer]]]]]]]]]]) + + A command-line program that loads a set of tests from *module* and runs them; + this is primarily for making test modules conveniently executable. + The simplest use for this function is to include the following line at the + end of a test script:: if __name__ == '__main__': unittest.main() @@ -1799,10 +1800,17 @@ if __name__ == '__main__': unittest.main(verbosity=2) + The *argv* argument can be a list of options passed to the program, with the + first element being the program name. If not specified or ``None``, + the values of :data:`sys.argv` are used. + The *testRunner* argument can either be a test runner class or an already created instance of it. By default ``main`` calls :func:`sys.exit` with an exit code indicating success or failure of the tests run. + The *testLoader* argument has to be a :class:`TestLoader` instance, + and defaults to :data:`defaultTestLoader`. + ``main`` supports being used from the interactive interpreter by passing in the argument ``exit=False``. This displays the result on standard output without calling :func:`sys.exit`:: @@ -1810,14 +1818,14 @@ >>> from unittest import main >>> main(module='test_module', exit=False) - The ``failfast``, ``catchbreak`` and ``buffer`` parameters have the same + The *failfast*, *catchbreak* and *buffer* parameters have the same effect as the same-name `command-line options`_. Calling ``main`` actually returns an instance of the ``TestProgram`` class. This stores the result of the tests run as the ``result`` attribute. .. versionchanged:: 2.7 - The ``exit``, ``verbosity``, ``failfast``, ``catchbreak`` and ``buffer`` + The *exit*, *verbosity*, *failfast*, *catchbreak* and *buffer* parameters were added. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 18:11:22 2012 From: python-checkins at python.org (ezio.melotti) Date: Mon, 30 Apr 2012 18:11:22 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogIzE0NTU4OiBkb2N1?= =?utf8?q?ment_the_module=2C_argv=2C_and_testLoader_args_of_unittest=2Emai?= =?utf8?q?n=2E?= Message-ID: http://hg.python.org/cpython/rev/06046a6943a7 changeset: 76670:06046a6943a7 branch: 3.2 parent: 76667:a54b6e321f1c user: Ezio Melotti date: Mon Apr 30 19:10:28 2012 +0300 summary: #14558: document the module, argv, and testLoader args of unittest.main. files: Doc/library/unittest.rst | 22 +++++++++++++++------- 1 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1926,9 +1926,10 @@ testLoader=unittest.defaultTestLoader, exit=True, verbosity=1, \ failfast=None, catchbreak=None, buffer=None, warnings=None) - A command-line program that runs a set of tests; this is primarily for making - test modules conveniently executable. The simplest use for this function is to - include the following line at the end of a test script:: + A command-line program that loads a set of tests from *module* and runs them; + this is primarily for making test modules conveniently executable. + The simplest use for this function is to include the following line at the + end of a test script:: if __name__ == '__main__': unittest.main() @@ -1939,10 +1940,17 @@ if __name__ == '__main__': unittest.main(verbosity=2) + The *argv* argument can be a list of options passed to the program, with the + first element being the program name. If not specified or ``None``, + the values of :data:`sys.argv` are used. + The *testRunner* argument can either be a test runner class or an already created instance of it. By default ``main`` calls :func:`sys.exit` with an exit code indicating success or failure of the tests run. + The *testLoader* argument has to be a :class:`TestLoader` instance, + and defaults to :data:`defaultTestLoader`. + ``main`` supports being used from the interactive interpreter by passing in the argument ``exit=False``. This displays the result on standard output without calling :func:`sys.exit`:: @@ -1950,7 +1958,7 @@ >>> from unittest import main >>> main(module='test_module', exit=False) - The ``failfast``, ``catchbreak`` and ``buffer`` parameters have the same + The *failfast*, *catchbreak* and *buffer* parameters have the same effect as the same-name `command-line options`_. The *warning* argument specifies the :ref:`warning filter ` @@ -1962,11 +1970,11 @@ This stores the result of the tests run as the ``result`` attribute. .. versionchanged:: 3.1 - The ``exit`` parameter was added. + The *exit* parameter was added. .. versionchanged:: 3.2 - The ``verbosity``, ``failfast``, ``catchbreak``, ``buffer`` - and ``warnings`` parameters were added. + The *verbosity*, *failfast*, *catchbreak*, *buffer* + and *warnings* parameters were added. load_tests Protocol -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 18:11:24 2012 From: python-checkins at python.org (ezio.melotti) Date: Mon, 30 Apr 2012 18:11:24 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_=2314558=3A_merge_with_3=2E2=2E?= Message-ID: http://hg.python.org/cpython/rev/6e541ed4e987 changeset: 76671:6e541ed4e987 parent: 76668:910a4b12c796 parent: 76670:06046a6943a7 user: Ezio Melotti date: Mon Apr 30 19:11:11 2012 +0300 summary: #14558: merge with 3.2. files: Doc/library/unittest.rst | 22 +++++++++++++++------- 1 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1920,9 +1920,10 @@ testLoader=unittest.defaultTestLoader, exit=True, verbosity=1, \ failfast=None, catchbreak=None, buffer=None, warnings=None) - A command-line program that runs a set of tests; this is primarily for making - test modules conveniently executable. The simplest use for this function is to - include the following line at the end of a test script:: + A command-line program that loads a set of tests from *module* and runs them; + this is primarily for making test modules conveniently executable. + The simplest use for this function is to include the following line at the + end of a test script:: if __name__ == '__main__': unittest.main() @@ -1933,10 +1934,17 @@ if __name__ == '__main__': unittest.main(verbosity=2) + The *argv* argument can be a list of options passed to the program, with the + first element being the program name. If not specified or ``None``, + the values of :data:`sys.argv` are used. + The *testRunner* argument can either be a test runner class or an already created instance of it. By default ``main`` calls :func:`sys.exit` with an exit code indicating success or failure of the tests run. + The *testLoader* argument has to be a :class:`TestLoader` instance, + and defaults to :data:`defaultTestLoader`. + ``main`` supports being used from the interactive interpreter by passing in the argument ``exit=False``. This displays the result on standard output without calling :func:`sys.exit`:: @@ -1944,7 +1952,7 @@ >>> from unittest import main >>> main(module='test_module', exit=False) - The ``failfast``, ``catchbreak`` and ``buffer`` parameters have the same + The *failfast*, *catchbreak* and *buffer* parameters have the same effect as the same-name `command-line options`_. The *warning* argument specifies the :ref:`warning filter ` @@ -1956,11 +1964,11 @@ This stores the result of the tests run as the ``result`` attribute. .. versionchanged:: 3.1 - The ``exit`` parameter was added. + The *exit* parameter was added. .. versionchanged:: 3.2 - The ``verbosity``, ``failfast``, ``catchbreak``, ``buffer`` - and ``warnings`` parameters were added. + The *verbosity*, *failfast*, *catchbreak*, *buffer* + and *warnings* parameters were added. load_tests Protocol -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 20:16:21 2012 From: python-checkins at python.org (ned.deily) Date: Mon, 30 Apr 2012 20:16:21 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEwNDMz?= =?utf8?q?=3A_Document_unique_behavior_of_=27os=2Egetgroups=27_on_Mac_OS_X?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/2468b58f7fce changeset: 76672:2468b58f7fce branch: 2.7 parent: 76669:55b2258c1c7c user: Ned Deily date: Mon Apr 30 11:13:16 2012 -0700 summary: Issue #10433: Document unique behavior of 'os.getgroups' on Mac OS X. files: Doc/library/os.rst | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -157,6 +157,20 @@ Availability: Unix. + .. note:: On Mac OS X, :func:`getgroups` behavior differs somewhat from + other Unix platforms. If the Python interpreter was built with a + deployment target of :const:`10.5` or earlier, :func:`getgroups` returns + the list of effective group ids associated with the current user process; + this list is limited to a system-defined number of entries, typically 16, + and may be modified by calls to :func:`setgroups` if suitably privileged. + If built with a deployment target greater than :const:`10.5`, + :func:`getgroups` returns the current group access list for the user + associated with the effective user id of the process; the group access + list may change over the lifetime of the process, it is not affected by + calls to :func:`setgroups`, and its length is not limited to 16. The + deployment target value, :const:`MACOSX_DEPLOYMENT_TARGET`, can be + obtained with :func:`sysconfig.get_config_var`. + .. function:: initgroups(username, gid) @@ -306,6 +320,10 @@ .. versionadded:: 2.2 + .. note:: On Mac OS X, the length of *groups* may not exceed the + system-defined maximum number of effective group ids, typically 16. + See the documentation for :func:`getgroups` for cases where it may not + return the same group list set by calling setgroups(). .. function:: setpgrp() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 20:16:22 2012 From: python-checkins at python.org (ned.deily) Date: Mon, 30 Apr 2012 20:16:22 +0200 Subject: [Python-checkins] =?utf8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEwNDMz?= =?utf8?q?=3A_Document_unique_behavior_of_=27os=2Egetgroups=27_on_Mac_OS_X?= =?utf8?q?=2E?= Message-ID: http://hg.python.org/cpython/rev/5c801899cd6d changeset: 76673:5c801899cd6d branch: 3.2 parent: 76670:06046a6943a7 user: Ned Deily date: Mon Apr 30 11:14:02 2012 -0700 summary: Issue #10433: Document unique behavior of 'os.getgroups' on Mac OS X. files: Doc/library/os.rst | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -227,6 +227,20 @@ Availability: Unix. + .. note:: On Mac OS X, :func:`getgroups` behavior differs somewhat from + other Unix platforms. If the Python interpreter was built with a + deployment target of :const:`10.5` or earlier, :func:`getgroups` returns + the list of effective group ids associated with the current user process; + this list is limited to a system-defined number of entries, typically 16, + and may be modified by calls to :func:`setgroups` if suitably privileged. + If built with a deployment target greater than :const:`10.5`, + :func:`getgroups` returns the current group access list for the user + associated with the effective user id of the process; the group access + list may change over the lifetime of the process, it is not affected by + calls to :func:`setgroups`, and its length is not limited to 16. The + deployment target value, :const:`MACOSX_DEPLOYMENT_TARGET`, can be + obtained with :func:`sysconfig.get_config_var`. + .. function:: initgroups(username, gid) @@ -389,6 +403,10 @@ Availability: Unix. + .. note:: On Mac OS X, the length of *groups* may not exceed the + system-defined maximum number of effective group ids, typically 16. + See the documentation for :func:`getgroups` for cases where it may not + return the same group list set by calling setgroups(). .. function:: setpgrp() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Apr 30 20:16:23 2012 From: python-checkins at python.org (ned.deily) Date: Mon, 30 Apr 2012 20:16:23 +0200 Subject: [Python-checkins] =?utf8?q?cpython_=28merge_3=2E2_-=3E_default=29?= =?utf8?q?=3A_Issue_=2310433=3A_merge?= Message-ID: http://hg.python.org/cpython/rev/e7d545a5f6bc changeset: 76674:e7d545a5f6bc parent: 76671:6e541ed4e987 parent: 76673:5c801899cd6d user: Ned Deily date: Mon Apr 30 11:15:38 2012 -0700 summary: Issue #10433: merge files: Doc/library/os.rst | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -238,6 +238,20 @@ Availability: Unix. + .. note:: On Mac OS X, :func:`getgroups` behavior differs somewhat from + other Unix platforms. If the Python interpreter was built with a + deployment target of :const:`10.5` or earlier, :func:`getgroups` returns + the list of effective group ids associated with the current user process; + this list is limited to a system-defined number of entries, typically 16, + and may be modified by calls to :func:`setgroups` if suitably privileged. + If built with a deployment target greater than :const:`10.5`, + :func:`getgroups` returns the current group access list for the user + associated with the effective user id of the process; the group access + list may change over the lifetime of the process, it is not affected by + calls to :func:`setgroups`, and its length is not limited to 16. The + deployment target value, :const:`MACOSX_DEPLOYMENT_TARGET`, can be + obtained with :func:`sysconfig.get_config_var`. + .. function:: initgroups(username, gid) @@ -425,6 +439,10 @@ Availability: Unix. + .. note:: On Mac OS X, the length of *groups* may not exceed the + system-defined maximum number of effective group ids, typically 16. + See the documentation for :func:`getgroups` for cases where it may not + return the same group list set by calling setgroups(). .. function:: setpgrp() -- Repository URL: http://hg.python.org/cpython From mark at hotpy.org Wed Apr 18 13:23:24 2012 From: mark at hotpy.org (Mark Shannon) Date: Wed, 18 Apr 2012 11:23:24 -0000 Subject: [Python-checkins] [Python-Dev] cpython: Fix #14600. Correct reference handling and naming of ImportError convenience In-Reply-To: References: Message-ID: <4F8EA42D.6090503@hotpy.org> Nick Coghlan wrote: > On Wed, Apr 18, 2012 at 7:57 AM, brian.curtin > wrote: >> diff --git a/Python/errors.c b/Python/errors.c >> --- a/Python/errors.c >> +++ b/Python/errors.c >> @@ -586,50 +586,43 @@ >> #endif /* MS_WINDOWS */ >> >> PyObject * >> -PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs) >> +PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) >> { >> - PyObject *val; >> + PyObject *args, *kwargs, *error; >> + >> + args = PyTuple_New(1); >> + if (args == NULL) >> + return NULL; >> + >> + kwargs = PyDict_New(); >> + if (args == NULL) >> + return NULL; Check return value of PyDict_New(); and DECREF args if it fails. >> + >> + if (name == NULL) >> + name = Py_None; >> + >> + if (path == NULL) >> + path = Py_None; > > Py_INCREF's? > > Regards, > Nick. >